Recipes · fd1
fd1 · FluxDesk's first production integrator
Walk through fd1's actual 4-tier permission model + how Mode B (request-on-behalf + dispatch) is wired today.
What this recipe is
fd1 is FluxDesk's first production-grade integrator. This recipe walks through its actual 4-tier permission model + how Mode B (request-on-behalf + webhook-driven dispatch) is wired today. Use it as a copy-from reference for any orchestrator that owns access-provisioning duties outside FluxDesk.
fd1 talks to FluxDesk over MCP + the v1 HTTP surface, holds a single flux-tools-… service-account token, and runs alongside (not inside) the FluxDesk container — Charter Art 4 (system boundary).
fd1 4-tier permission map (production)
Tier 0 is granted automatically on first onboard; tiers 1-3 are opt-in via the team-support flow below.
| Tier | Catalog slug | Category | Grants | Backend action |
|---|---|---|---|---|
| 0 | inbound-fd1default · auto | 🔑 接入凭证 / Access Credentials | fd1 → employee inbox push channel | auto-issued on first onboard |
| 1 | fd1.codex-backendopt-in · MCP | 🤖 公司付费 AI 订阅 / Paid AI Subscriptions | Codex backend (公司 OpenAI 订阅) | fd1 codex login <user>OAuth device-auth on admin Mac |
| 2 | fd1.claude-backendopt-in · MCP | 🤖 公司付费 AI 订阅 / Paid AI Subscriptions | Claude Code backend (公司 Anthropic 订阅) | fd1 claude login <user>OAuth device-auth |
| 3 | bastion-terminal-accessreuses FluxDesk row | 🖥 vibe coding 开发环境申请 | fluxdeskone SSH terminal access | fd1 employee ssh-grant <user> |
⚠️ Status: MVP (manual dispatch)
Today the request → approve → provision loop is human-bridged. After an admin clicks ✓ 审批通过 in /team-support the team_support.approved webhook fires into the void — fd1's receiver isn't shipped yet. The admin then runs fd1 employee dispatch <req_id> to complete the cycle.
Webhook-driven automation is planned for v0.20.x, once fd1 deploys the webhook receiver to the fluxdeskone host behind a Cloudflare tunnel. Steps 2 → 3 below become automatic then; the rest of the model doesn't change.
Admin requests a grant on a user's behalf
One fd1 CLI call per tier. Internally this hits FluxDesk MCP create_team_support_request_on_behalf which records a pending request + pushes an inbox notification to the admin queue.
# Step 1 · admin runs fd1 CLI on behalf of an employee.
# Under the hood this calls FluxDesk MCP create_team_support_request_on_behalf.
fd1 employee request-grant alice fd1.codex-backend \
--reason "Codex Code 公司订阅 enrollment" \
--use-case "review-only access for vibe-coding sessions"# Same call, raw HTTP (what the fd1 CLI actually does).
curl -X POST https://my.fluxdesk.net/mcp \
-H "Authorization: Bearer flux-tools-EXAMPLE…" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_team_support_request_on_behalf",
"arguments": {
"subject_email": "[email protected]",
"catalog_slug": "fd1.codex-backend",
"reason": "Codex Code 公司订阅 enrollment",
"use_case": "review-only access for vibe-coding sessions"
}
}
}'Admin approves in the FluxDesk UI
Admin opens /team-support → 待审批 → ✓ 审批通过. FluxDesk sets request.status = "approved" and emits the team_support.approved outbound webhook (see outbound docs for HMAC verification). Today this webhook fires into the void — fd1's receiver isn't shipped yet.
Admin runs `fd1 employee dispatch` (manual bridge)
fd1 looks up the approved request, maps its catalog_slug to a backend command, and kicks off the matching action — for Codex/Claude this is an OAuth device-auth flow on the admin's Mac. On success, fd1 emits a fd1.<x>.enabled event back into the employee's inbox with usage instructions.
# Step 3 · MANUAL bridge (current MVP).
# After admin clicks ✓ 审批通过 at /team-support, fd1 dispatch:
# - looks up the approved request by id
# - maps catalog_slug → backend command
# - kicks off the OAuth device-auth flow on the admin's Mac
# - on success, emits fd1.<x>.enabled back into FluxDesk inbox
fd1 employee dispatch <request_id>
# Examples per tier:
fd1 codex login alice # tier 1 — Codex
fd1 claude login alice # tier 2 — Claude
fd1 employee ssh-grant alice # tier 3 — fluxdeskone SSHfd1 emits the inbox-ready event
After the backend command succeeds, fd1 hits /api/v1/events with the employee's personal inbound token (claimed once via /api/v1/tokens/claim; same email → same token until rotated, so replay-safe).
# After OAuth success, fd1 emits a fd1.<x>.enabled event back into
# FluxDesk so alice gets an inbox notification with usage instructions.
curl -X POST https://my.fluxdesk.net/api/v1/events \
-H "Authorization: Bearer flux-in-pers-EXAMPLE…" \
-H "Content-Type: application/json" \
-d '{
"event_type": "fd1.codex.enabled",
"title": "Codex Code 公司订阅已开通",
"body": "你已加入公司 OpenAI Codex 订阅。终端运行 codex 即可。",
"tone": "positive"
}'Revoke flow
Admin runs fd1 employee revoke → MCP revoke_catalog_approval → FluxDesk marks the approval revoked, logs the audit row, and emits team_support.withdrawn. Once the v0.20.x webhook receiver lands, fd1 tears down the source system automatically (e.g. fd1 codex logout). Today the admin runs the matching logout manually.
# Off-board · admin runs fd1 revoke.
# Under the hood this calls FluxDesk MCP revoke_catalog_approval.
fd1 employee revoke alice fd1.codex-backend
# Current MVP: webhook receiver not yet shipped, so admin runs the
# matching backend logout manually after revoke records the audit row.
fd1 codex logout aliceEvent namespace
fd1 emits these 11 event types back into FluxDesk inbox via /api/v1/events. Namespace pattern is fd1.<entity>.<action> past-tense.
fd1.account.onboardednew hire signal accepted
fd1.account.offboardedtermination signal accepted
fd1.codex.enabledCodex login OK
fd1.codex.disabledfd1.claude.enabledClaude Code login OK
fd1.claude.disabledfd1.ssh.grantedbastion key authorized
fd1.ssh.revokedfd1.repo.createdfd1.repo.collaborator_addedfd1.repo.archived
fd1 as a reference implementation
fd1 is the canonical worked example for Mode B (admin orchestrator + MCP request-on-behalf). If you're wiring your own provisioner, copying fd1's shape is the fastest path: one service-account tools token, MCP for the write path, outbound webhook for fan-out, inbound events for the user-facing follow-up.
This recipe is maintained in collaboration with fd1. Updates land via PR — or via the FluxDesk team mirroring fd1's own docs/fd1-for-fluxdesk-team.md when fd1 publishes a new version. Catalog slugs and event types above are canonical: fd1 reviews this page when their backend changes.
Have a similar setup? We're happy to add your recipe here. [email protected]