Skip to content
Merged
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
32 changes: 25 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
mindmap go-build go-test go-lint go-fmt go-vet go-tidy \
lint-md-links script-test test \
e2e-test behaviour-test lint-eval-cases functional-tests \
wasm-build mint-cf-worker-test
wasm-build wasm-stage mint-cf-worker-test

# Let Go automatically download the toolchain version required by go.mod.
# This ensures local builds use the right version without manual intervention.
Expand Down Expand Up @@ -33,7 +33,8 @@ help:
@echo " lint-eval-cases - Lint eval case definitions (annotations.yaml completeness)"
@echo " functional-tests - Run functional agent tests (requires EVAL_ORG, FULLSEND_DIR, GH_TOKEN, GCP creds)"
@echo " wasm-build - Build mintcore WASM binary and report gzip size vs Workers limits"
@echo " mint-cf-worker-test - Run CF mint Worker bridge smoke tests (stub until workersrc lands)"
@echo " wasm-stage - Build and stage WASM + wasm_exec.js into CF Worker source tree"
@echo " mint-cf-worker-test - Build WASM, install deps, and run CF Worker bridge smoke tests"

# Install all development tools needed for linting, formatting, and pre-commit hooks.
# Prerequisites: uv (https://docs.astral.sh/uv/) and go (https://go.dev/)
Expand Down Expand Up @@ -141,12 +142,29 @@ wasm-build:
fi
@echo "==> WASM build OK"

# Stub CI contract for CF mint Worker bridge smoke tests (#5481).
# Populated by #5427 / follow-up with wasm-stage + workersrc npm test.
# Stage WASM binary and wasm_exec.js into the CF Worker source tree.
# Run after wasm-build to prepare for `wrangler dev` or `wrangler deploy`.
WORKERSRC_DIR := internal/dispatch/cf/workersrc
wasm-stage: wasm-build
@echo "==> Staging WASM artifacts into $(WORKERSRC_DIR)..."
cp cmd/mint-wasm/mint.wasm $(WORKERSRC_DIR)/mintcore.wasm
Comment thread
ifireball marked this conversation as resolved.
cp "$$(go env GOROOT)/lib/wasm/wasm_exec.js" $(WORKERSRC_DIR)/wasm_exec.js
@echo "==> Staged: $(WORKERSRC_DIR)/mintcore.wasm, $(WORKERSRC_DIR)/wasm_exec.js"

# Run CF Worker bridge smoke tests.
# Works on a clean checkout: stages WASM, installs npm deps, runs vitest.
# Uses `npm install` (not `npm ci`) because the workersrc lockfile is not
# committed — the dep tree is small enough that install-time resolution is
# acceptable. Switch to `npm ci` if a lockfile is added later.
# Do not rename: .github/workflows/mint-cf-worker-test.yml calls this target.
mint-cf-worker-test:
@echo "==> mint-cf-worker-test: stub (no CF Worker bridge tests yet)"
@echo " Replace this stub when internal/dispatch/cf/workersrc lands (#5427)."
mint-cf-worker-test: wasm-stage
@echo "==> Installing CF Worker npm dependencies..."
cd $(WORKERSRC_DIR) && npm install --no-audit --no-fund
@echo "==> Type-checking CF Worker source (production + test files)..."
cd $(WORKERSRC_DIR) && npm run typecheck && npm run typecheck:tests
@echo "==> Running CF Worker bridge smoke tests..."
cd $(WORKERSRC_DIR) && npm test
@echo "==> Worker smoke tests passed"

lint-md-links:
lychee --offline --no-progress --include-fragments --exclude-path node_modules --exclude-path experiments '**/*.md'
Expand Down
2 changes: 2 additions & 0 deletions docs/contributing/go-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ When changing `internal/mint/main.go`, always copy it to `internal/dispatch/gcf/

**Standalone mint:** `cmd/mint/` is a standalone HTTP server variant of the token mint that serves the same purpose as the GCF mint (`internal/mint/`) but runs without GCP infrastructure. Both use the shared `internal/mintcore/` library for token minting logic; they differ only in deployment model (filesystem PEM vs Secret Manager, JWKS vs STS verification). It supports custom role permissions via `CUSTOM_ROLE_PERMISSIONS` and a fallback proxy to an upstream mint. It has its own `go.mod` and tests run from `cmd/mint/`.

**CF Worker adapter:** `internal/dispatch/cf/workersrc/` is a thin TypeScript Cloudflare Worker adapter that consumes mintcore via WASM (`cmd/mint-wasm`). The adapter handles I/O only (Worker secrets, host fetch, Fetch Request/Response mapping); all mint logic stays in Go. The Go WASM bridge registers `mintcoreInitMint` and `mintcoreHandleFetch` on `globalThis` via `syscall/js`; changes to these entry points in `cmd/mint-wasm` or to the contracts they consume in `internal/mintcore/` require updating `workersrc/src/index.ts` to match.

**Mint client:** `internal/mintclient/` is the Go client for calling the mint service at runtime. It exchanges a GitHub Actions OIDC JWT for a role-scoped installation token. Unlike `internal/mint/` and `internal/mintcore/`, it has no embedded copies or sync requirements.

The `internal/mintcore/` module is shared between the mint and devmint. Its files are also embedded for Cloud Function deployment at `internal/dispatch/gcf/mintsrc/mintcore/*.embed`. When changing any file in `internal/mintcore/`, sync it to the corresponding `.embed` file under `mintsrc/mintcore/`. Note: the mint's `go.mod.embed` uses `replace mintcore => ./mintcore` (not `../mintcore`), because `provisioner.go` rewrites the replace directive at bundle time to match the deployed directory layout.
Expand Down
1 change: 1 addition & 0 deletions docs/guides/dev/cli-internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ var executableFiles = map[string]struct{}{
| `cmd/mint/` | ~285 | Standalone mint server (no GCP dependency) |
| `internal/mintcore/` | ~1425 | Shared mint library (handler, OIDC verifiers, GitHub API) |
| `internal/dispatch/gcf/provisioner.go` | ~1959 | GCP infrastructure provisioner |
| `internal/dispatch/cf/workersrc/` | ~800 | CF Worker adapter for mint (WASM bridge, I/O only) |
| `internal/sandbox/sandbox.go` | ~459 | OpenShell sandbox operations |
| `internal/harness/harness.go` | ~486 | Harness YAML parsing |
| `internal/layers/layers.go` | ~159 | Layer interface and stack |
Expand Down
6 changes: 6 additions & 0 deletions internal/dispatch/cf/workersrc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Build artifacts staged by `make wasm-stage` (not committed).
mintcore.wasm
wasm_exec.js

# npm install output.
node_modules/
25 changes: 25 additions & 0 deletions internal/dispatch/cf/workersrc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
Comment thread
ifireball marked this conversation as resolved.
"name": "fullsend-mint-worker",
"version": "0.0.0",
"private": true,
"type": "module",
"description": "Thin Cloudflare Worker adapter for the fullsend token mint (WASM)",
Comment thread
ifireball marked this conversation as resolved.
"scripts": {
"prestage": "cd ../../../.. && make wasm-stage",
"stage": "echo 'Staged mintcore.wasm and wasm_exec.js via make wasm-stage'",
"predev": "npm run stage",
"dev": "wrangler dev",
Comment thread
ifireball marked this conversation as resolved.
"predeploy": "npm run stage",
"deploy": "wrangler deploy",
"typecheck": "tsc --noEmit",
"typecheck:tests": "tsc --noEmit --project tsconfig.test.json",
"test": "vitest run"
Comment thread
ifireball marked this conversation as resolved.
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.8.0",
"@cloudflare/workers-types": "^5.20260708.1",
"typescript": "^5.8.0",
"vitest": "^3.2.0",
"wrangler": "^4.0.0"
}
}
32 changes: 32 additions & 0 deletions internal/dispatch/cf/workersrc/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Smoke tests for the CF Worker mint bridge.
Comment thread
ifireball marked this conversation as resolved.
Comment thread
ifireball marked this conversation as resolved.
//
// These tests run inside @cloudflare/vitest-pool-workers (Miniflare)
// with the real Go WASM binary. They verify that the bridge boots —
// not full mint OIDC coverage. Run after `make wasm-stage` so that
// mintcore.wasm and wasm_exec.js are present.
import { SELF } from "cloudflare:test";
import { describe, expect, it } from "vitest";

describe("mint worker bridge smoke", () => {
it("boots and serves /health", async () => {
const resp = await SELF.fetch("https://worker.test/health");
expect(resp.status).toBe(200);

const body = await resp.text();
expect(body).toContain("ok");
});

it("returns 404 for unknown paths", async () => {
const resp = await SELF.fetch("https://worker.test/nonexistent");
// Go's ServeHTTP routes this; unmatched paths return 404.
expect(resp.status).toBe(404);
});

it("returns 405 for non-POST on /v1/token", async () => {
const resp = await SELF.fetch("https://worker.test/v1/token", {
method: "GET",
});
// The mint handler rejects non-POST on the token endpoint.
expect(resp.status).toBe(405);
});
});
Loading
Loading