feat: add development-only local mint server#1784
Conversation
Site previewPreview: https://31601812-site.fullsend-ai.workers.dev Commit: |
ReviewFindingsMedium
Low
Previous runReviewFindingsMedium
Low
Previous run (2)ReviewFindingsMedium
Low
Previous run (3)ReviewFindingsLow
Previous run (4)ReviewFindingsMedium
Low
Previous runReviewFindingsMedium
Low
Previous run (2)ReviewFindingsMedium
Low
Previous run (3)ReviewFindingsLow
Previous run (4)ReviewFindingsMedium
Low
Previous run (5)ReviewFindingsMedium
Low
Previous run (6)ReviewFindingsMedium
Low
Previous run (7)ReviewFindingsMedium
Low
Info
Previous run (8)ReviewFindingsMedium
Low
Info
Previous run (9)ReviewFindingsMedium
Low
Info
Previous run (10)ReviewFindingsMedium
Low
Info
Previous run (11)ReviewFindingsHigh
Low
Info
Previous run (12)ReviewFindingsMedium
Low
Info
Previous run (13)ReviewFindingsMedium
Low
Info
Previous run (14)ReviewFindingsHigh
Low
Info
Previous run (15)ReviewFindingsMedium
Low
Info
Previous run (16)ReviewFindingsHigh
Low
Info
Previous run (17)ReviewFindingsMedium
Low
Info
|
|
Rebased on main (which now includes #1783 mintcore extraction). All review findings addressed: Medium:
Low:
Also updated mintcore API calls to match the merged #1783 interface ( |
|
All findings addressed: Medium:
Low:
|
Adds a dev mint server that runs locally without any GCP infrastructure,
making it easier to evaluate and develop fullsend.
Key changes:
- New `internal/devmint` package: HTTP dev mint using OIDC verification
and on-disk PEM storage; supports cloudflared tunnel for remote access
- New `internal/mintcore` package extracted to share JWT generation and
OIDC verification between the dev mint and Cloud Function mint
- `fullsend mint run` CLI command to start the dev mint server
- `--mint-data-dir` flag on `admin install` writes PEMs directly to disk
- `--skip-mint-check` now skips GCP provisioning only; GitHub Apps are
still created (HTTP permitted for loopback addresses, 127.0.0.0/8)
- ADR 0043 documents the updated `--skip-mint-check` semantics
- Terminology standardized on "dev mint" throughout (package, docs, code)
Security:
- OIDC verification enabled by default (disable with --insecure-no-auth)
- Default bind address is 127.0.0.1; tunnel flag uses cloudflared
- --insecure-no-auth and --tunnel are mutually exclusive
- --insecure-no-auth errors when combined with a non-loopback --bind
- --tunnel requires explicit --allowed-workflows; wildcard needs '*'
- allowedWorkflows wildcard resolved in Start() not New()
- /v1/status and /v1/token require OIDC auth by default
- handleToken and handleStatus: fail-closed on nil OIDC claims
- handleToken and handleStatus: explicit RepositoryOwner == s.org check
- loadFromDisk: validates org and role fields
- Role names validated with ValidateRoleName (rejects double-hyphens)
- SecretExists closure validates role before building file path
- Stdout drained in StartTunnel; cloudflared early-exit via exitCh
- Per-repo install path guards GCP calls with !skipMintCheck
- --mint-data-dir validated to require --skip-mint-check
- validateSkipMintCheck uses net.ParseIP().IsLoopback()
- X-Fullsend-Dev-Mint response header removed to avoid fingerprinting
Code quality:
- Package-level godoc for internal/devmint
- resolveAppSetupMintProject helper deduplicates install-path logic
- Neutral error message language throughout
- ADR 0033 supersession link; ADR 0043 citations in architecture.md
- cli-internals.md Phase 6 PEM diagram reflects all storage options
- /v1/status roles sorted alphabetically
Testing:
- TestInstallCmd_MintDataDirRequiresSkipMintCheck_{PerOrg,PerRepo}
- TestOrgMismatchReturns403, TestNilClaimsFailClosed
- TestStartTunnel_*: CI-safe fake-cloudflared pattern
- TestValidateSkipMintCheck, TestStorePEMToDisk
- TestResolveAppSetupMintProject, TestMintDataDir{SecretExists,StoreSecret}Callback
- Existing devmint and appsetup test suites extended
Signed-off-by: Greg Allen <gallen@redhat.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| │ ├── unenroll <org|owner/repo> # Remove org/repo from mint | ||
| │ └── status [org] # Inspect mint state and PEM health | ||
| │ ├── status [org] # Inspect mint state and PEM health | ||
| │ └── run # Run standalone token mint (no GCP required) |
There was a problem hiding this comment.
I kind of assumed we would end up with a production-worthy stand-alone version of the mint, but dev-mint.md lists many limitations that really indicate this is only for dev use, so I wonder if we should indicate this with the command name, because I do want to ultimately reach a point where we have a command that runs a production mint.
Or perhaps we need to aim toward this becoming a prod-ready deployment, file issues for the gaps, and print a loud warning at statup while it isn't.
There was a problem hiding this comment.
My goal was a mint that could be standalone and allow someone to easily install and evaluate fullsend, hence all the limitation. We can expand that if necessary. Let me know what you think.
There was a problem hiding this comment.
I want to make it so the command set under fullsend mint is good for setting up and managing all kinds of mint architectures, from GCP function, to Cloudflare worker to k8s deployment to local , but its hard for me to figure out what this needs to look like. I'm trying to see how to make the right choices now so we don't need a messy user-visible change later
| Specifically: | ||
|
|
||
| - GitHub Apps **are still created** when `--skip-app-setup` is not set. | ||
| - PEM storage is determined by flag combination, evaluated in order: |
There was a problem hiding this comment.
I wonder if we should introduce variables like --mint-platform=gcp|local and --mint-secret-store=gcp|file that then require other variables as needed. This implicit emergence of the resulting architecture from the variables being set is confusing and will get more confusing when we support other deployment options such as Cloudflare and K8s.
I'm not sure if we should have a simple variable that select the platform and implies all other settings like secret loading backend and OIDC verification backend or wither we should have different setting to let the user select different combinations (though not all combinationsmight be possible or make sense)
|
@ggallen how does this relates to your standalone mint PR? |
|
Does #2537 supersedes this? |
Summary
Add a standalone token mint for local development and evaluation. This eliminates the need for GCP infrastructure (Secret Manager, WIF, Cloud Functions) to get started with fullsend.
Dev mint server (
internal/devmint/)--insecure-no-authflag for local dev/v1/statusendpoint gated behind OIDC auth (matching production mint behavior)CLI changes
fullsend mint runcommand with--data-dir,--port,--tunnel,--insecure-no-auth,--oidc-audienceflags--mint-data-dirflag onfullsend admin install— writes PEMs directly to disk instead of Secret Manager--mint-url/--skip-mint-checkvalidation (allowshttp://localhost,http://127.0.0.1,http://[::1]for dev mint)storePEMToDisk()for disk-based PEM persistence during installDocumentation
docs/guides/infrastructure/dev-mint.mdmint runto CLI command tree incli-internals.mdReview focus
storePEMToDisksafe against path traversal via role names?--insecure-no-authand--mint-data-dircompose correctly with existing flags?Test plan
go test ./internal/devmint/...— tests passgo test ./internal/cli/...— CLI tests pass (including IPv6 localhost)go vet ./...— cleango test ./...— full test suite passesfullsend mint run→ tunnel →fullsend admin install→ agent runs🤖 Generated with Claude Code
Closes #1963