Skip to content

ci(ci): publish maya.scenario.com behind a Vercel proxy - #18

Merged
qchantel merged 24 commits into
mainfrom
ci/site
Nov 13, 2026
Merged

qchantel merged 24 commits into
mainfrom
ci/site

Conversation

@qchantel

@qchantel qchantel commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR change?

The plug-in had no page to download it from, and its downloads were not counted, unlike photoshop.scenario.com. This adds maya.scenario.com, as photoshop-plugin does: site/index.html (one page, the pictures of docs/media), published to GitHub Pages by pages.yml after each release with the release's ZIP under /download/ (checked against its SHA256SUMS and build attestation) and download/latest.json; and tools/site_proxy, the Vercel project that holds the domain, forwards it to Pages, counts ZIP downloads in PostHog without identifying visitors, and answers /download/latest. The middleware and its tests are ported from photoshop-plugin; the tests run in CI on the Node of .nvmrc (new site proxy job, required by ci-ok).

Stacked on #17; retarget to main once #16 and #17 are merged. After merge, an administrator does what RELEASING.md ("Site") lists: Pages source "GitHub Actions", the Vercel project maya-plugin-site rooted at tools/site_proxy with POSTHOG_PROJECT_TOKEN and the domain, and the Route 53 CNAME in scenario-labs/management. Until then the page publishes to the Pages address only.

Validation

  • uv run --with pytest pytest -q passes; for changes that touch Maya code, tools/test_maya.sh passes too. The Maya version and OS are listed below.
  • python3 tools/lint.py, uvx ruff check . and uvx ruff format --check . pass.
  • Packaging changes: the release ZIP installs by dragging install_scenario.py onto a Maya viewport with no errors or warnings in the Script Editor, and its contents were inspected.
  • Maya or UI changes were tried in a Maya session (tools/test_maya_gui.sh or by hand), with before/after screenshots for UI.
  • Live status is stated: python3 tools/contract_check.py (free) when calls to Scenario change; any paid run had prior authorization for its project and budget.

Commands and results:

  • uv run --python 3.13 --with pytest pytest -q: 181 passed, including tests/unit/test_site.py (the page links /download/latest, has no em dash, names only support@scenario.com, every local file it uses exists; stamping fills version and ref and refuses anything else).
  • node --test tests/site/*.test.js on Node 24: 11 passed (download counts, anonymous ids, client classes, ignored paths and resumed downloads, no token no count, /download/latest redirect and its fallback to the releases page).
  • The page stamped and rendered in headless Chrome at 1280 px and 520 px wide: layout holds, no horizontal scroll. The pictures it uses come from docs/media and show only the masked "My Team / My Project".
  • Not run: pages.yml itself (it publishes only from main of this repository), and the proxy on Vercel (the project does not exist yet). No Maya code changed.

Public content

  • No credentials, tokens, signed URL query strings, or private account, team, project, job or asset IDs are included.
  • No personal paths, machine details, agent session IDs or spend anecdotes are included.

Rules

  • The spending rules in AGENTS.md still hold (price check first, single-use quotes, paid calls sent once, SCENARIO_NO_SPEND).
  • No unrelated manual version or changelog edits; documentation matches the resulting behavior.

Authorship and licensing

  • Human review of the complete diff is recorded before merge.
  • Adopted third-party code or assets keep their compatible licenses and attribution; original contributions are licensed under MIT, the repository license.

Written with Claude Code (Claude Opus 5.5). The middleware, its tests, the publish steps and the version stamping are ported from photoshop-plugin (MIT, same organization); the Scenario logo is a trademark of Scenario, as its file says.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a responsive landing page for Scenario for Maya, with product information, feature descriptions, installation instructions for Maya 2025–2027, and links to guides, releases, checksums, build attestations, and privacy information.
    • Added a lantern-generation example with a video and step-by-step images.
    • Added a published website with links to release downloads. The latest-download link redirects to the current package when available, or to the GitHub releases page otherwise.
    • Added download counting for eligible package requests.

qchantel and others added 3 commits November 13, 2026 14:55
…f the hosted MCP

The plug-in sent every call to the hosted MCP, a service written for agents:
errors came back as text, so a paid call's outcome was guessed with patterns,
and each call made an extra hop through a token exchange.

- RestBackend keeps the ScenarioBackend interface and calls the REST API
  with scenario-sdk 2.5.0: teams and projects, models (filtered by
  capability), generation with dryRun for price checks, jobs, assets, 3D
  conversion links, multipart uploads.
- core/rest.py builds the SDK's HTTP client (OS trust store, system
  proxies, no redirects) and keeps the spending rules: paid calls are sent
  once with retries off, and a token the API's gateway refuses (403 with
  x-amzn-errortype) is renewed and resent once.
- tools/vendor_sdk.py unpacks the SDK and its dependencies, pinned by
  SHA-256, into _vendor/sdk; core/sdk.py loads the pydantic_core build for
  the running Maya, after the packages installed in Maya's Python but before
  setuptools/_vendor, whose older typing_extensions Maya puts on the path.
- SCENARIO_API_URL replaces SCENARIO_MCP_URL; recommend and wait_jobs go,
  nothing called them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tus test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and publish its changelog

There was no release: no version bump, no changelog from the merged
pull requests, and no package to download.

- release-please keeps the release PR (version in pyproject.toml,
  scenario_maya/__init__.py and ScenarioForMaya.mod, changelog); merging it
  builds scenario-maya-X.Y.Z.zip from the release commit, checks it byte for
  byte, attests it, attaches it with SHA256SUMS and a Sigstore bundle to a
  draft, checks it again on macOS, then publishes the draft.
- tools/package.py builds a reproducible ZIP (module, vendored SDK,
  install_scenario.py, licence); tools/release/ holds the package check,
  the draft finder and the contributors section, ported from
  photoshop-plugin.
- publish-changelog posts each published release's notes to
  www.scenario.com/changelog; RELEASING.md lists the settings it needs.
- The first release is 0.1.0: the manifest starts at 0.0.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qchantel
qchantel requested review from a team and hervenivon as code owners November 13, 2026 14:14
@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Adds a product landing page and a Pages publishing workflow. Adds a Vercel proxy for download redirects and event tracking, with middleware tests and CI coverage.

Changes: Site publishing and download proxy

Layer / File(s) Summary
Landing page and version stamping
site/index.html, tools/release/stamp_site.py, tests/unit/test_site.py
Adds the product page and a command that replaces version and ref markers. Tests check page links, local references, and stamping inputs.
Pages publishing workflow
.github/workflows/pages.yml, .lycheeignore, AGENTS.md, RELEASING.md
Adds manual, push, and qualifying release-completion triggers. The workflow selects site content, stamps the page, verifies release artifacts when present, and deploys a Pages artifact. Documentation describes publishing triggers, content, and setup.
Download proxy and CI coverage
tools/site_proxy/*, tests/site/site-proxy.test.js, .github/workflows/ci.yml, AGENTS.md
Adds Vercel rewrites and middleware for latest-download redirects and qualified download events. Tests cover routing, version caching, and event handling. CI runs the middleware tests and requires their job for ci-ok.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant VercelMiddleware
  participant PagesOrigin
  participant PostHog
  Browser->>VercelMiddleware: Request latest download or package ZIP
  VercelMiddleware->>PagesOrigin: Read latest.json
  PagesOrigin-->>VercelMiddleware: Return published version
  VercelMiddleware->>PostHog: Send qualified download event
  VercelMiddleware-->>Browser: Redirect or continue request
Loading
Merge Risk: Low · up to cc57e

The landing page plays a looping demo video and animated images that visitors cannot pause. This can bother motion-sensitive visitors but does not block use of the page. Adding video controls, and handling the GIFs, is a small follow-up that can be done before or soon after merge.

Pre-merge checks: Passed 2

Check name Status Explanation
Title check Passed The title "ci(ci): publish maya.scenario.com behind a Vercel proxy" names the main change: publishing the maya.scenario.com download site through a Vercel proxy. The changeset adds the Pages workflow,…
Description check Passed The description follows the template's main sections: What does this PR change, Validation, Public content, Rules, and Authorship and licensing. It states the problem, what each part does, the post-me…
Full details: Title check

Explanation

The title "ci(ci): publish maya.scenario.com behind a Vercel proxy" names the main change: publishing the maya.scenario.com download site through a Vercel proxy. The changeset adds the Pages workflow, the site page, and the proxy middleware. The scope "ci" is a weaker fit, since most of the change is site and tooling, but the title still matches the primary change. The title is 55 characters, within the 120-character limit, and uses an imperative summary with no trailing period.

Full details: Description check

Explanation

The description follows the template's main sections: What does this PR change, Validation, Public content, Rules, and Authorship and licensing. It states the problem, what each part does, the post-merge admin steps, and the validation commands with results. The template's checklist items are ticked for checks the author ran, and unrun checks are left unticked, as the template requires. The template asks for a scope-aware title and a Closes/Refs line; the description references a stacked PR (#17) but does not use a Closes or Refs line for an issue. The description also includes a generated-by note that the template does not require. These gaps are minor, so the description is mostly complete.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 3a02364e-0bbc-4e68-a39e-b0179e5e9bd0
Commits

Reviewing files that changed from the base of the PR and between 6accbf1 and 4943acd.

Files ignored due to path filters: 1

  • site/assets/scenario-logo.svg is excluded by !**/*.svg
Files selected for processing: 11

  • .github/workflows/ci.yml
  • .github/workflows/pages.yml
  • .lycheeignore
  • AGENTS.md
  • RELEASING.md
  • site/index.html
  • tests/site/site-proxy.test.js
  • tests/unit/test_site.py
  • tools/release/stamp_site.py
  • tools/site_proxy/middleware.ts
  • tools/site_proxy/vercel.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

Recent review details

Context from checks skipped due to timeout: 1

  • GitHub Check: CodeRabbit
Additional context used

Code guidelines: 1

RELEASING.md — auto-discovered
Path-based instructions: 1

Applicability reference: AGENTS.md: # maya-plugin: agent instructions The Maya module is `ScenarioForMaya/`.

CodeRabbit inference engine (RELEASING.md)

Files:

  • tools/site_proxy/middleware.ts
  • tools/site_proxy/vercel.json
ast-grep (0.51.1)

tests/site/site-proxy.test.js

[warning] 34-49: Use https protocol over http
Context: http.createServer((request, response) => {
const url = request.url || "";
const prefix = url.replace(//download/latest.json$/, "");
if (request.method === "GET" && latest.has(prefix)) {
latestReads.set(prefix, (latestReads.get(prefix) || 0) + 1);
const file = latest.get(prefix);
response.writeHead(file.status, { "content-type": "application/json" }).end(JSON.stringify({ version: file.version }));
return;
}
let text = "";
request.on("data", (chunk) => (text += chunk));
request.on("end", () => {
received.push({ path: url, body: JSON.parse(text) });
response.writeHead(posthogStatus).end();
});
})
Note: [CWE-319] Cleartext Transmission of Sensitive Information. Security best practice.

(https-protocol-missing)

[warning] 86-86: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(path.join(ROOT, "tools", "site_proxy", "vercel.json"), "utf8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename)

tests/unit/test_site.py

[warning] 18-18: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(PAGE, encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

tools/release/stamp_site.py

[warning] 39-39: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

[warning] 44-44: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "w", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

OpenGrep (1.33.0)

tools/site_proxy/middleware.ts

[ERROR] 58-58: A nonliteral argument is passed to exec/execSync. Identify the receiver: Node child_process methods execute shell commands, while regular-expression and database methods have different contracts. For shell execution, prefer execFile or spawn with an argument array.

(coderabbit.command-injection.exec-js)

zizmor (1.31.1)

.github/workflows/pages.yml

[error] 16-16: use of fundamentally insecure workflow trigger (dangerous-triggers): workflow_run is almost always used insecurely

(dangerous-triggers)

[warning] 48-48: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

[warning] 129-129: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

[info] 37-37: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

[info] 124-124: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

Additional comments: 3

tools/site_proxy/vercel.json: 1

1-7: LGTM!

tests/site/site-proxy.test.js: 1

1-216: LGTM!

.github/workflows/ci.yml: 1

36-50: LGTM!

Also applies to: 134-134

@github-code-quality

github-code-quality Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Code coverage overview

Languages: Python

Python / code-coverage/python

main 53bdda4 ci/site cc57ee7 +/-
87% 87% 0%

ℹ️ Calculations represent line coverage. Results may change as calculations are updated.


Updated November 13, 2026 15:59 UTC

…rcel proxy

The plug-in had no page to download it from, and its downloads were not
counted, unlike photoshop.scenario.com and blender.scenario.com.

- site/index.html, one page in the style of the other plug-in sites, with
  the pictures of docs/media; pages.yml publishes it to GitHub Pages after
  each release with the release's ZIP under /download/ (checked against its
  SHA256SUMS and build attestation) and download/latest.json.
- tools/site_proxy (vercel.json, middleware.ts), ported from
  photoshop-plugin: forwards maya.scenario.com to Pages, counts ZIP
  downloads in PostHog without identifying visitors, and answers
  /download/latest.
- tools/release/stamp_site.py fills the page with the release's version;
  the proxy tests run in CI on the Node of .nvmrc, required by ci-ok.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qchantel qchantel changed the title ci(site): publish maya.scenario.com from the latest release behind a Vercel proxy ci(ci): publish maya.scenario.com from the latest release behind a Vercel proxy Nov 13, 2026
…age after it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qchantel

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

qchantel and others added 17 commits November 13, 2026 15:38
- A paid call whose answer cannot be read is Not confirmed, not refused.
- RestClient refuses a base URL that is not HTTPS (loopback excepted).
- An API key reads every /projects page until one has its project.
- upload_complete reads an upload again while it is not readable yet.
- The GUI install stage checks the label against the key's own project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n the user's step

A live generation quoted 12.75 CU and showed 11 charged: a job's cuCost is
its main action only, and the quality gate's 1.75 CU is in cuCostDetails.
The charge is now the sum of cuCostDetails when the job has them.

The GUI generate stage undid the playblast's own step instead of the card;
it now undoes that step first. SCENARIO_GUI_URL_FILE lets an agent open the
sign-in page in a browser it drives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	tests/gui/gui_checks.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	tests/gui/gui_checks.py
Base automatically changed from ci/release to main November 13, 2026 15:49
qchantel and others added 2 commits November 13, 2026 16:50
# Conflicts:
#	AGENTS.md
#	RELEASING.md
…and who can use it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qchantel qchantel changed the title ci(ci): publish maya.scenario.com from the latest release behind a Vercel proxy ci(ci): publish maya.scenario.com behind a Vercel proxy Nov 13, 2026
@qchantel
qchantel merged commit e7a804e into main Nov 13, 2026
24 of 25 checks passed
@qchantel
qchantel deleted the ci/site branch November 13, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant