Skip to content
Closed
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

Materialize accepts only exact SHA-256 pins or a bounded relative `-r` include (no `.`/`..`); a lone `--require-hashes` directive is not trust evidence. See [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md).
Conflict-scope roots fail closed when the immediate parent directory is a symbolic link.
Cursor Cloud Agents cannot complete Figma MCP OAuth against `https://mcp.figma.com/mcp` (allowlisted-client catalog; Cloud unsupported). Desktop/CLI remain the MCP path. Cloud Agents that must read Figma files store `FIGMA_ACCESS_TOKEN`, run `python3 scripts/ci/figma_rest_auth.py`, then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>`. See [`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md).
33 changes: 32 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,35 @@ sequenceDiagram
- Rust remains the psychometric arithmetic owner. Repair never substitutes
Python for scoring math.

## Figma Cloud Agent REST fallback

```mermaid
flowchart TD
Need["Cloud Agent needs Figma"]
Mcp{"Figma MCP OAuth available?"}
Desktop["Desktop / CLI: Settings → Tools and MCP → Figma → Connect"]
Token{"FIGMA_ACCESS_TOKEN set?"}
Whoami["python3 scripts/ci/figma_rest_auth.py"]
File["python3 scripts/ci/figma_rest_file.py file-key-or-url"]
Mint["Mint a Figma PAT with file_content:read and store the secret"]

Need --> Mcp
Mcp -->|"yes, Desktop or CLI"| Desktop
Mcp -->|"no, Cloud or Automation"| Token
Token -->|"no"| Mint
Mint --> Whoami
Token -->|"yes"| Whoami
Whoami --> File
```

Cloud Agents never complete Figma MCP OAuth. Whoami alone is not file
read. The file helper allowlists the file or branch key and node ids,
opens a pinned `HTTPSConnection("api.figma.com")`, and prints a
token-free JSON outline with geometry, solid fills, text, and
auto-layout. `--images` returns expiring PNG URLs. Desktop/CLI Figma
MCP remains the `get_design_context` path. See
[`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md).

## Quality gates

`scripts/ci/` ships with 100% statement/branch coverage and 100% docstrings.
Expand All @@ -107,4 +136,6 @@ tests pin workflow structure and governance prose so drift fails closed.
- [`docs/doctoring/hourly-nvidia-nim-autofix.md`](docs/doctoring/hourly-nvidia-nim-autofix.md)
— current increment's repair-worker decision and APA 7th citations.
- [`docs/doctoring/fast-mlsirm-hourly-review-caller.md`](docs/doctoring/fast-mlsirm-hourly-review-caller.md)
— product-specific psychometric repair heartbeat and scientific gates.
— product-specific psychometric repair heartbeat and scientific gates.
- [`docs/doctoring/figma-cloud-agent-mcp-auth.md`](docs/doctoring/figma-cloud-agent-mcp-auth.md)
— Cloud Agent Figma MCP boundary and REST file-read fallback.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Semantic Versioning where the repository publishes a release.

### Added

- Added Cloud Agent Figma REST helpers `scripts/ci/figma_rest_auth.py` and `scripts/ci/figma_rest_file.py` that verify `FIGMA_ACCESS_TOKEN` against pinned `GET /v1/me` and then read an allowlisted `GET /v1/files/{file_key}` (optional `/nodes` or `/images`) without printing the secret, returning geometry, solid fills, text, auto-layout, and optional expiring PNG URLs. Desktop/CLI Figma MCP remains the `get_design_context` path.
- Added a trusted pull-request comment router for `@cwl-noema-review` and review-only `@opencode-agent` dispatches, with an organization sweep, exact-head receipts, repository allowlisting, fixed runners, immutable checkout pins, and a permanent 100% statement/branch/docstring quality gate.
- Added exact-base `uv.lock` materialization that reconstructs standalone nested projects with a checksum-pinned official `uv` exporter, isolated frozen/offline execution, strict exact-pin and SHA-256 output validation, and complete Python 3.10/3.14 quality evidence.
- Added a permanent exact-head contract workflow for the hourly review-repair scheduler, immutable reusable-workflow source, NVIDIA NIM model boundary, credential isolation, and fail-closed unattended-agent permissions.
Expand Down Expand Up @@ -39,6 +40,7 @@ Semantic Versioning where the repository publishes a release.

### Security

- Pin Figma REST calls to `http.client.HTTPSConnection("api.figma.com")`, allow only the `X-Figma-Token` header, allowlist file keys and node ids (CWE-22), parse locators without fetching them (CWE-918), reject control characters in the token (CWE-113), and cap whoami/file bodies so `file://` and unbounded reads cannot leave the helper.
- Reject `.github/` and `scripts/ci/` from review-thread-derived autofix path authority so an untrusted inline reviewer cannot authorize the write-capable repair agent to modify workflows, CODEOWNERS, actions, scheduler code, or CI helpers that govern its own control plane.
- Require the model-write snapshot and exact-path allowlist to remain outside the pull-request worktree, checking both absolute and resolved locations so repository-local controls and outside-looking symlinks resolving into the repository fail closed before they can authorize or verify model changes.
- Snapshot the complete pre-model worktree for ordinary and conflict repair and reject every model-caused created, deleted, modified, mode-changed, retargeted, ignored, dangling, directory-backed, external-link, metadata-race, or out-of-scope path before staging or push.
Expand All @@ -55,6 +57,7 @@ Semantic Versioning where the repository publishes a release.

### Documentation

- Added an APA 7 doctoring record for the Cloud Agent Figma MCP OAuth boundary, REST whoami and file-read helpers, operator next-action contract, and Figma file-endpoint citations.
- Added an APA 7 doctoring record for conflict-control evidence isolation, including the Strix-reported trust-boundary failure, test-first remediation, canonical-path rule, operator contract, rollback, MITRE CWE-22, and current GitHub Actions secure-use guidance.
- Added operator and APA 7 doctoring records for the hourly cadence, immutable source identity, NVIDIA NIM provider and secret boundary, high-reasoning Mistral Small 4 writer, model-process credential isolation, modular MSA ownership, product-specific caller activation, verification contract, and rollback.
- Added DiskSage operational documentation for the hourly RCA loop, bounded retry cadence, permission model, standalone and MSA reuse, verification, rollback, and APA 7 references.
Expand Down
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,8 @@ repeatable compile command.
cross-repo references as `owner/repo#num` or full URLs; durable knowledge in the repo/Project, not
private memory; one roadmap phase at a time) are defined in `docs/CWL-MASTER-CONTEXT.md` §7 and
apply here.
- **Figma on Cloud Agents is REST-only.** Do not retry MCP Connect against
`https://mcp.figma.com/mcp`. Store `FIGMA_ACCESS_TOKEN`, run
`python3 scripts/ci/figma_rest_auth.py`, then
`python3 scripts/ci/figma_rest_file.py <file-key-or-url>`. Desktop/CLI keep
the full MCP path. See `docs/doctoring/figma-cloud-agent-mcp-auth.md`.
1 change: 1 addition & 0 deletions docs/CWL-MASTER-CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ GitHub **Project #1** is the shared source of truth. Structure: real **Issues**
- **BLOCKER B1**: org GitHub Actions effectively HALTED (~86 queued, ~0 in_progress org-wide) — likely the Actions monthly SPENDING CAP. Blocks ALL PR checks/merges + the Cloudflare DNS run (nameservers). Fix (org-admin): raise the Actions spending limit OR add a self-hosted runner. Nothing merges until then.
- **Decisions pending**: (D1) Code Security enablement vs the CodeQL-only code_scanning ruleset (osv/trivy/scorecard SARIF upload) — a private repo needs GHAS seats; reconcile or make those checks non-required. (D2) trivy `limit-severities-for-sarif: true` (gate only CRITICAL/HIGH) — held pending the user's strict-security preference.
- **Built this session, PR-open, awaiting merge (B1)**: see Project #1 PRs (contextual-orchestrator cost/routing #46 + naruon#973; pg-llm-batch; keyverse Keycloak; inkspan; SBOM #361; opencode auto-retry #360; Strix neutral #349 + emit #358; appguardrail collector #254; auto-rebase #357; noema #359/naruon#970; PDF-DOM naruon#965/newsdom#300; SDP #11; fast-mlsirm GPGPU #109; scopeweave #284/naruon#971; fuzzing 10 PRs (found+fixed 2 real naruon bugs); Cloudflare DNS/Pages #362; this protocol #363; planning #974). Human step: report the mapasevo21 malware file (github user-attachments) to GitHub Abuse; rotate the xtrmLLMBatchPython-leaked keys; the org-admin runner/decisions above.
- **Figma MCP on Cloud Agents (2026-08-16)**: `https://mcp.figma.com/mcp` is OAuth-only and not supported in Cursor Cloud Agents / Automations. Desktop IDE and CLI remain the MCP path. Cloud Agents that must read Figma files store `FIGMA_ACCESS_TOKEN`, run `python3 scripts/ci/figma_rest_auth.py`, then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>` against the REST API. See `docs/doctoring/figma-cloud-agent-mcp-auth.md`.

---
*Keep this current. Update Project #1 as the live tracker; this file is the narrative brief a fresh agent reads to reconstruct the whole picture.*
Expand Down
161 changes: 161 additions & 0 deletions docs/doctoring/figma-cloud-agent-mcp-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Figma MCP auth on Cursor Cloud Agents

## Incident

A Cursor Cloud Agent tasked with Figma work discovers the official Figma MCP
server (`https://mcp.figma.com/mcp`) in an `error` state: live tool discovery
fails and no Figma tools are available. Re-running Connect / OAuth from the
Cloud Agent cannot repair it. Desktop Cursor and the Cursor CLI remain able to
complete the same OAuth flow.

## Live evidence (2026-08-16)

Unauthenticated `initialize` against the remote MCP endpoint:

```http
POST https://mcp.figma.com/mcp
HTTP/2 401
WWW-Authenticate: Bearer resource_metadata="https://mcp.figma.com/.well-known/oauth-protected-resource",scope="mcp:connect",authorization_uri="https://api.figma.com/.well-known/oauth-authorization-server"
```

Body: `Unauthorized`.

The same environment can reach Figma (`HEAD`/`POST` complete; no egress block).
`GET https://api.figma.com/v1/me` without a token returns
`{"status":403,"err":"Invalid token"}`. No `FIGMA_*` environment variables are
present on the Cloud Agent VM.

Figma's remote MCP is OAuth 2.1 with PKCE and an allowlisted MCP client
catalog. Cursor Cloud Agents are not a supported client for that catalog.

## Decision

Do not treat Figma MCP as available inside Cloud Agents or Cloud Automations.
Cursor staff stated this explicitly: Figma MCP is not supported in Cloud agents;
it is fully supported in the IDE and the CLI (Neilson, 2026). There is no
estimated timeline; support is a joint Cursor/Figma change.

Use two disjoint auth paths:

| Surface | Auth | Capability |
|---|---|---|
| Cursor Desktop / CLI | Figma MCP OAuth (`Settings → Tools & MCP → Figma → Connect`) | Full MCP toolset (`get_design_context`, `use_figma`, write-to-canvas, …) |
| Cursor Cloud Agent | Figma personal or plan access token in `FIGMA_ACCESS_TOKEN` | REST only: `python3 scripts/ci/figma_rest_auth.py` then `python3 scripts/ci/figma_rest_file.py <file-key-or-url>` (`X-Figma-Token` only, pinned `https://api.figma.com/v1/me` and `/v1/files/{key}`) |

A personal or plan access token does **not** unlock Figma MCP on Cloud Agents.
It only authorizes the REST API. Do not commit the token. Do not put it in
`environment.json`, workflow YAML, or chat output.

Prefer a **plan access token** for organization Cloud Agent fleets
(admin-managed, expiry up to one year; Figma, 2026a). Use a personal access
token only when the operator is acting on their own account (maximum 90 days).
Both kinds are stored in the same secret name. Whoami and file bodies are
capped (64 KiB / 8 MiB). File keys and node ids are allowlisted before they
enter the request path (CWE-22; MITRE, 2026a). Locators are parsed and never
fetched; TLS already pins `api.figma.com` (CWE-918; MITRE, 2026b). Control
characters in the token are rejected so they cannot split `X-Figma-Token`
(CWE-113; MITRE, 2026c). The opener still refuses every header except
`X-Figma-Token`.

## Operator procedure

1. **Desktop / CLI MCP (preferred for design-to-code).** In Cursor Desktop,
Settings → Tools & MCP → Figma → Connect, then Allow access in the Figma
browser window. Confirm with a Figma MCP `whoami` from a desktop agent.
2. **Cloud Agent REST fallback.** In Figma: account menu → Settings → Security
→ Personal access tokens → Generate new token. Name it for Cloud Agents.
Grant `file_content:read` (add comment scopes only if needed). Maximum
expiry is 90 days (Figma, 2025). Store the value as the Cursor environment
secret `FIGMA_ACCESS_TOKEN`.
3. **Verify the secret without printing it:**

```bash
python3 scripts/ci/figma_rest_auth.py
```

Success prints a handle/id/email line. Missing or rejected tokens exit
non-zero and never echo the secret. The helper opens a pinned
`http.client.HTTPSConnection("api.figma.com")` to `GET /v1/me` and refuses
any other URL, so Semgrep `dynamic-urllib-use-detected` does not apply
(`urllib.request.urlopen` is not used).
4. **Read the file the buyer asked for.** Whoami is not file read. After the
secret verifies, run:

```bash
python3 scripts/ci/figma_rest_file.py 'https://www.figma.com/design/<file_key>/<name>?node-id=12-34'
```

Or pass the file key and node id directly:

```bash
python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34
python3 scripts/ci/figma_rest_file.py '<file_key>' --node-id 12:34 --images
```

The helper allowlists the file or branch key (10-128 letters or digits)
and node ids (including instance ids such as `I12:34;56:78`) before they
enter the path, opens the same pinned `api.figma.com` origin, and prints
a token-free JSON outline. `GET /v1/files/:key?depth=2` is pages and
top-level frames. A URL with `?node-id=` uses `GET /v1/files/:key/nodes`,
where `depth` counts levels under the selected node (Figma, 2026c). The
outline keeps `absoluteBoundingBox`, SOLID fills, TEXT `characters` and
type, auto-layout padding, constraints, `thumbnailUrl`, and bounded
component/style names. `--images` returns HTTPS PNG URLs that expire
after 30 days (Figma, 2026c). `file://`, `http://`, userinfo, and
`api.figma.com` locators are refused. Branch URLs
(`/design/<file_key>/branch/<branch_key>/...`) use the branch key.
Implement from that outline on Cloud Agents. Desktop/CLI Figma MCP
`get_design_context` remains the richer design-to-code path; do not
retry MCP Connect here.

## Why MCP Connect cannot be finished here

Figma only accepts MCP clients listed in its catalog (Figma, 2026b). The
Cloud Agent MCP client is not on that list, so the OAuth authorize endpoint
answers `Forbidden` / `401` before a browser grant can be created. Asking the
user to "click Connect" inside a Cloud Agent or Automation therefore cannot
succeed. The same Connect button works in the desktop IDE because that client
is allowlisted.

## APA 7th references

Figma. (2025). *Changelog*. Figma Developer Docs. Retrieved August 16, 2026,
from https://developers.figma.com/docs/rest-api/changelog/

Figma. (2026a). *Personal access tokens*. Figma Developer Docs. Retrieved
August 16, 2026, from
https://developers.figma.com/docs/rest-api/personal-access-tokens/

Figma. (2026b). *Set up the remote server (recommended)*. Figma Developer Docs.
Retrieved August 16, 2026, from
https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/

Figma. (2026c). *Endpoints*. Figma Developer Docs. Retrieved August 16, 2026,
from https://developers.figma.com/docs/rest-api/file-endpoints/

Fielding, R., Nottingham, M., & Reschke, J. (Eds.). (2022). *HTTP semantics*
(RFC 9110). Internet Engineering Task Force.
https://www.rfc-editor.org/rfc/rfc9110

Hardt, D., Parecki, A., & Lodderstedt, T. (Eds.). (2025). *The OAuth 2.1
authorization framework* (Internet-Draft draft-ietf-oauth-v2-1). Internet
Engineering Task Force. Retrieved August 16, 2026, from
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1

MITRE. (2026a). *CWE-22: Improper limitation of a pathname to a restricted
directory ('Path Traversal')*. https://cwe.mitre.org/data/definitions/22.html

MITRE. (2026b). *CWE-918: Server-side request forgery (SSRF)*.
https://cwe.mitre.org/data/definitions/918.html

MITRE. (2026c). *CWE-113: Improper neutralization of CRLF sequences in HTTP
headers ('HTTP Request/Response Splitting')*.
https://cwe.mitre.org/data/definitions/113.html

Neilson, K. (2026, June 10). Reply in *Figma MCP shows "Forbidden" in
Automations / Cloud Agents*. Cursor Forum. Retrieved August 16, 2026, from
https://forum.cursor.com/t/figma-mcp-shows-forbidden-in-automations-cloud-agents/162969

Sakimura, N., Bradley, J., & Agarwal, N. (2015). *Proof Key for Code Exchange
by OAuth public clients* (RFC 7636). RFC Editor.
https://doi.org/10.17487/RFC7636
Loading
Loading