Skip to content

feat(pymthouse): builder-sdk 0.6.0 and RFC 8693 API key exchange#424

Merged
eliteprox merged 3 commits into
mainfrom
chore/pymthouse-builder-sdk
Jul 17, 2026
Merged

feat(pymthouse): builder-sdk 0.6.0 and RFC 8693 API key exchange#424
eliteprox merged 3 commits into
mainfrom
chore/pymthouse-builder-sdk

Conversation

@eliteprox

@eliteprox eliteprox commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bump @pymthouse/builder-sdk to the published builder-sdk 0.6.0 contract.
  • Switch API-key → signer exchange to the app-scoped RFC 8693 endpoint (POST /api/v1/apps/{clientId}/oidc/token), replacing the old signer-session path.
  • Treat composite app_<24hex>_pmth_… keys as DMZ Bearer credentials; update adapter/client tests and PymtHouse docs accordingly.

Test plan

  • Confirm CI installs resolve @pymthouse/builder-sdk
  • Run pymthouse-adapter / pymthouse-client unit tests.
  • Exercise Get API Key / validate signer path with a composite key and with OIDC token exchange.
  • Smoke developer-api UI key creation against preview PymtHouse.

Summary by CodeRabbit

  • Improvements

    • Updated PymtHouse billing authentication to support app-scoped API key exchanges using the RFC 8693 token-exchange flow.
    • Added support for both composite app_*_* and legacy pmth_* presented API keys.
    • Improved signer routing and authorization handling for composite keys.
    • Updated Developer API screens with clearer guidance for creating, presenting, and exchanging PymtHouse keys.
  • Documentation

    • Revised integration guidance, endpoint details, key formats, routing expectations, and verification steps.
    • Updated examples and SDK references for the latest PymtHouse integration behavior.

…hange

- Updated the dependency for @pymthouse/builder-sdk to version 0.6.0, using a local file link until published.
- Refactored the API key exchange process to utilize the new RFC 8693 token exchange endpoint (`POST /api/v1/apps/{clientId}/oidc/token`), replacing the previous signer-session exchange.
- Updated relevant tests and documentation to reflect changes in the API key handling and exchange process.

This change enhances the integration with the PymtHouse API by adopting the latest standards for token exchange, ensuring better compatibility and security.
@github-actions github-actions Bot added scope/shell Shell app changes plugin/developer-api Developer API plugin size/L Large PR (201-500 lines) labels Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

⚠️ This PR is large (202 lines changed). Consider splitting it into smaller PRs for easier review.

Replace local file: links so CI/Vercel can resolve the published package.
@github-actions github-actions Bot added size/M Medium PR (51-200 lines) and removed size/L Large PR (201-500 lines) labels Jul 16, 2026
@eliteprox
eliteprox enabled auto-merge (squash) July 16, 2026 23:44
@eliteprox
eliteprox requested a review from Copilot July 16, 2026 23:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates NaaP’s PymtHouse integration to the @pymthouse/builder-sdk 0.6.0 contract and switches API-key → signer authentication over to the app-scoped RFC 8693 token exchange endpoint (POST /api/v1/apps/{clientId}/oidc/token). It also updates UI copy and documentation to reflect that newly issued presented keys can be composite (app_<24hex>_<secret>) in addition to bare pmth_*.

Changes:

  • Bump @pymthouse/builder-sdk from 0.5.00.6.0 across app + developer-api plugin, and update package-lock.json accordingly.
  • Replace the prior signer-session exchange call pattern with RFC 8693 form-encoded token exchange and update parsing/tests.
  • Update Developer API UI + docs to describe composite key behavior and how signing/exchange works.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
plugins/developer-api/frontend/src/pages/DeveloperView.tsx Recognize composite app_*_* keys and update UI messaging for PymtHouse key behavior.
plugins/developer-api/frontend/package.json Bump @pymthouse/builder-sdk to 0.6.0.
plugins/developer-api/backend/package.json Bump @pymthouse/builder-sdk to 0.6.0.
package-lock.json Lockfile update for @pymthouse/builder-sdk@0.6.0.
docs/pymthouse-integration.md Refresh integration docs for composite keys + new /oidc/token exchange.
apps/web-next/src/lib/pymthouse-signer-exchange-config.ts Update comments to reflect app-scoped RFC 8693 token exchange endpoint.
apps/web-next/src/lib/pymthouse-client.ts Implement RFC 8693 form POST to /api/v1/apps/{clientId}/oidc/token and update error text.
apps/web-next/src/lib/pymthouse-client.test.ts Update unit tests to assert form-encoded RFC 8693 request + new path.
apps/web-next/src/lib/billing/pymthouse-adapter.ts Treat composite keys as direct Bearer to signer DMZ; use token exchange for bare pmth_*.
apps/web-next/src/lib/billing/pymthouse-adapter.test.ts Update adapter tests to use composite app_<24hex>_... keys and new behaviors.
apps/web-next/package.json Bump @pymthouse/builder-sdk to 0.6.0.
Comments suppressed due to low confidence (1)

apps/web-next/src/lib/pymthouse-client.ts:452

  • The fallback error code 'signer_session_exchange_failed' is now misleading since this path is an RFC 8693 token exchange (/oidc/token). Updating the code string makes logs/telemetry easier to interpret and avoids consumers keying off an outdated name.
    throw new PmtHouseError(description, {
      status: response.status,
      code: typeof body.error === 'string' ? body.error : 'signer_session_exchange_failed',
      details: body,
    });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/developer-api/frontend/src/pages/DeveloperView.tsx Outdated
Comment thread apps/web-next/package.json
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Deployment failed with the following error:

Creating the Deployment Timed Out.

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
naap-platform Ready Ready Preview Jul 17, 2026 4:27pm

Request Review

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026
Composite keys can be presented as Bearer; bare pmth_* must be exchanged first.
@github-actions github-actions Bot added size/L Large PR (201-500 lines) and removed size/M Medium PR (51-200 lines) labels Jul 17, 2026
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

PymtHouse API-key exchange now uses the app-scoped RFC 8693 OIDC endpoint with form-encoded inputs. Composite presented keys are routed directly, while bare keys are exchanged for signer tokens. Tests, UI guidance, documentation, and Builder SDK pins were updated.

Changes

PymtHouse API-key flow

Layer / File(s) Summary
App-scoped OIDC token exchange
apps/web-next/src/lib/pymthouse-client.ts, apps/web-next/src/lib/pymthouse-client.test.ts, apps/web-next/src/lib/pymthouse-signer-exchange-config.ts
The client posts RFC 8693 form fields to /api/v1/apps/{clientId}/oidc/token, parses signer-token responses, and updates related errors, tests, and configuration documentation.
Composite signer endpoint resolution
apps/web-next/src/lib/billing/pymthouse-adapter.ts, apps/web-next/src/lib/billing/pymthouse-adapter.test.ts
The adapter uses isCompositeApiKey to forward composite keys directly and exchanges bare keys for signer access tokens, with updated resolver coverage.
Presented-key UI and integration contract
plugins/developer-api/frontend/src/pages/DeveloperView.tsx, docs/pymthouse-integration.md, apps/web-next/package.json, plugins/developer-api/*/package.json
The UI and documentation describe composite or bare presented keys, and Builder SDK dependencies are pinned to version 0.6.0.

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

Sequence Diagram(s)

sequenceDiagram
  participant DeveloperView
  participant PymthouseAdapter
  participant exchangeApiKeyForSignerSession
  participant PymtHouseOIDCTokenEndpoint
  participant SignerDMZ
  DeveloperView->>PymthouseAdapter: provide presented API key
  PymthouseAdapter->>PymthouseAdapter: classify composite or bare key
  PymthouseAdapter->>SignerDMZ: route composite key as bearer
  PymthouseAdapter->>exchangeApiKeyForSignerSession: exchange bare key
  exchangeApiKeyForSignerSession->>PymtHouseOIDCTokenEndpoint: POST RFC 8693 form data
  PymtHouseOIDCTokenEndpoint-->>PymthouseAdapter: return signer access token
  PymthouseAdapter->>SignerDMZ: use signer token
Loading

Possibly related PRs

Suggested labels: scope/packages

Suggested reviewers: seanhanca

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: the builder-sdk upgrade and the move to RFC 8693 API key exchange.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/pymthouse-builder-sdk

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web-next/src/lib/pymthouse-client.ts (1)

431-439: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Defensively check JSON response format to prevent runtime errors.

If the token exchange endpoint (or a proxy/gateway in front of it) returns a JSON literal like null instead of an object, typeof body === 'object' remains true. Subsequent access to properties like body.error_description or body.token will throw a TypeError and crash the thread.

Validating that the parsed response is a non-null, non-array object inside the try block ensures that unexpected payloads safely trigger the generic PmtHouseError catch block.

🛡️ Proposed defensive check
   let body: Record<string, unknown>;
   try {
-    body = (await response.json()) as Record<string, unknown>;
+    const parsed = await response.json();
+    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
+      throw new Error('Response is not a JSON object');
+    }
+    body = parsed as Record<string, unknown>;
   } catch {
     throw new PmtHouseError('API key token exchange returned invalid JSON', {
       status: 502,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web-next/src/lib/pymthouse-client.ts` around lines 431 - 439, Update the
JSON parsing in the token exchange response flow to validate that the parsed
value is a non-null, non-array object before assigning it to body. Treat null,
arrays, and other JSON primitives as invalid responses so they follow the
existing PmtHouseError path instead of reaching body.error_description or
body.token access.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/web-next/src/lib/pymthouse-client.ts`:
- Around line 431-439: Update the JSON parsing in the token exchange response
flow to validate that the parsed value is a non-null, non-array object before
assigning it to body. Treat null, arrays, and other JSON primitives as invalid
responses so they follow the existing PmtHouseError path instead of reaching
body.error_description or body.token access.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2098f3a2-9db3-4232-aea9-191cb0770e0c

📥 Commits

Reviewing files that changed from the base of the PR and between 411c310 and 7fe4dd2.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !package-lock.json
📒 Files selected for processing (10)
  • apps/web-next/package.json
  • apps/web-next/src/lib/billing/pymthouse-adapter.test.ts
  • apps/web-next/src/lib/billing/pymthouse-adapter.ts
  • apps/web-next/src/lib/pymthouse-client.test.ts
  • apps/web-next/src/lib/pymthouse-client.ts
  • apps/web-next/src/lib/pymthouse-signer-exchange-config.ts
  • docs/pymthouse-integration.md
  • plugins/developer-api/backend/package.json
  • plugins/developer-api/frontend/package.json
  • plugins/developer-api/frontend/src/pages/DeveloperView.tsx

@eliteprox
eliteprox merged commit db9a600 into main Jul 17, 2026
27 checks passed
@eliteprox
eliteprox deleted the chore/pymthouse-builder-sdk branch July 17, 2026 16:35
seanhanca added a commit that referenced this pull request Jul 17, 2026
Capture builder-sdk 0.6.0 format change, live validate/inference re-probe,
and revised action plan now that #424 is on main.

Co-authored-by: Cursor <cursoragent@cursor.com>
seanhanca added a commit that referenced this pull request Jul 17, 2026
Document post-#424 resolveSignerEndpoint branches, required PYMTHOUSE_* prod
vars, and local simulation proving legacy dot-format PYMTHOUSE_API_KEY triggers
the fail-safe token-bundle fallback when per_key_remote_signer is ON.

Co-authored-by: Cursor <cursoragent@cursor.com>
seanhanca added a commit that referenced this pull request Jul 18, 2026
…_SECRET drift

keys/validate returns 503 "Billing provider unavailable" (reason: mint_failed).
Confirmed pymthouse healthy + current M2M secret mints end-to-end; prod Vercel
env holds a stale/revoked secret. Not a pymthouse outage, not a builder-sdk
0.6.0 (#424) regression. Owner: qiang (prod env + redeploy). Composite direct
signer path unaffected.

Co-authored-by: Cursor <cursoragent@cursor.com>
seanhanca added a commit that referenced this pull request Jul 20, 2026
…t superseded/dead

mintUserSignerJwtForExternalUser is coded, merged (#406/#410) and reached prod
behind per_key_remote_signer, but is now orphaned: neither main nor
feat/opaque-session-signer-endpoint call it. Superseded by composite-bearer
(#421, Fix A) and api-key signer-session exchange (#412/#424). Plan file
NAAP-SIGNER-JWT-EXCHANGE-PLAN.md does not exist; SDK mintUserSignerToken grant
was abandoned upstream (500).

Co-authored-by: Cursor <cursoragent@cursor.com>
seanhanca added a commit that referenced this pull request Jul 21, 2026
…on doc (#430)

* fix(billing): remove dead user-JWT signer mint + correct opaque-session doc

The billed pymthouse `/generate-live-payment` webhook is JWT/composite-key
only: it rejects a bare opaque `pmth_` session with 401 "not a JWT", while the
unbilled `/sign-orchestrator-info` accepts it (looser auth) — which masked the
asymmetry. main's `resolveSignerEndpoint()` already forwards the correct
composite `app_<24hex>_pmth_<secret>` bearer (or exchanges a bare key for a
signer JWT), so this change:

- Deletes the orphaned Fix B `mintUserSignerJwtForExternalUser()` +
  `UserSignerJwt` (zero non-test call sites; superseded by #421/#412/#424) and
  its unit tests.
- Rewrites the `resolveSignerEndpoint()` doc comment, which still referenced the
  removed user-JWT mint, to accurately describe the composite-bearer /
  api-key-exchange credential resolution and the billed-webhook asymmetry.
- Drops the now-dangling `mintUserSignerJwtForExternalUser` mock + assertions
  from the adapter test.

No behavior change: the composite-bearer forwarding and the
`PER_KEY_REMOTE_SIGNER_FLAG` gating are untouched; no feature-flag defaults
changed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(e2e): Run 57 — billed E2E on LR-orch via composite-bearer path (PR #430)

Verify PR #430 (forward composite app_..._pmth_... bearer, not opaque session)
end-to-end against the Live Runner orchestrator (liverunner-staging-1):

- validate → 200, signerSession {url,headers} with COMPOSITE bearer (PR #430 design)
- signer /sign-orchestrator-info on LR-orch → 200 (composite accepted, not "not a JWT")
- billed /generate-live-payment on LR-orch → 400 "missing or zero priceInfo"
  (LR zero-pricing config, John/orch infra — NOT an auth/#430 issue)
- generation → 400 "Could not verify job creds" (unpaid, downstream of pricing)
- byoc-staging-1 control (same composite bearer) → 200 + real image (stack intact)

Verdict: PR #430 composite-bearer fix HOLDS on the LR path; remaining blocker is
LR-orch zero-pricing (unchanged from Run 55/55b). Adds LR/composite probe scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(audit): trace unit_kind billing-unit lifecycle + OpenMeter unit-metering gap

unit_kind is display-only (advertised on /capabilities, back-filled for AI caps);
it is never sent to orch, never in the create_signed_ticket event, and never read
by the collector or OpenMeter meters (which sum network fee grouped by pipeline/
model only). Documents producer->transport->collector->consumer map with file:line
and per-hop owners.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add Storyboard signer routing (Daydream vs pymthouse) architecture

Document the production decision flow for how a Storyboard generation
request selects the Daydream signer (signer.daydream.live, type:lv2v)
vs the pymthouse per-key DMZ signer (type:byoc). The authoritative
switch is SIGNER_FROM_VALIDATE + AUTH_VALIDATE_URL in the SDK service
(_effective_signer), keyed on a naap_ bearer + validate signerSession;
the python-gateway only derives payment type from the signer hostname.
Includes a Mermaid diagram, per-hop file:line citations, and the current
prod state (per-key path OFF; Daydream/lv2v is live).

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add pymthouse-e2e skill for the billed E2E test path

Reusable skill/instructions doc (Claude Code or Cursor) covering the
validate → signer → payment → orchestrator → metering flow, env-var
config (placeholders only, no secrets), per-scenario run commands,
result interpretation, troubleshooting, and coverage caveats.

* docs: make liverunner-staging-1 (LR-orch) a first-class E2E scenario

Add a dedicated LR-orch section (env, commands, per-stage expected
results per Run 57), a byoc-staging-1 control contrast, and clarify the
env table + interpreting section that LR zero-pricing is the expected,
known blocker (John/orch-infra) while PR #430 auth holds.

* docs: make pymthouse-e2e a true hand-off skill for agents

Add a "For the AI agent" runbook at the top: step 0 prompts the user for
required inputs (naap key OR composite bearer + signer URL), then the agent
sets up env, resolves signer credentials, runs the default happy path, and
emits a PASS/FAIL report. Adds a mandatory-vs-optional inputs checklist, a
NAAP_KEY -> validate credential-derivation path, a report template table, and
a warning that run57 has no GATEWAY_SRC default. No secrets embedded.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add BYOC-to-live-runner migration analysis + merge strategy

Evidence-based HTML report covering byoc-staging-1 deploy state, PR/branch
merge-state, live-runner parity matrix, minimal-merge recommendation,
phased retire plan, and regression risks. Analysis only; no code changes.

* docs(audit): resolve byoc-staging-1 orch branch/commit/image ambiguity

Pinned image livepeer/go-livepeer:feat-remote-signer-byoc-v2 maps to branch
feat/remote-signer-byoc-v2 @ be5a669e (built 2026-05-13, sha256:9f1abba6),
NOT the local dev branch fix/byoc-e2e-v1-and-type-byoc @ 8ddd08ea (17 ahead /
119 behind). Adds build mapping (docker/metadata-action type=ref,event=branch),
Docker Hub digest evidence, and the gcloud/docker-inspect command to confirm
the live VM (deploy-byoc.sh does not wire ORCH_IMAGE, so the pin is docs-only).

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add Storyboard MCP performance & capacity investigation

Test-based root-cause report (HTML). Findings: slowness / "out of
capacity" is still happening, concentrated in image-to-video —
seedance-i2v-fast runs 176-181s (advertised ~30s) and fails ~2/3 of
the time against a ~180s SDK /inference abort ceiling. Root cause is
per-capability Livepeer orchestrator/GPU capacity (no warm
orchestrator), amplified by the hard timeout. t2v and ffmpeg are
healthy. Includes latency/failure tables, server telemetry, ranked
hypotheses, worst offenders, and recommendations. Total test spend $1.62.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add Storyboard MCP performance-bias skill / adaptive agent proposal

Review-ready proposal comparing Option A (explicit two-mode "prefer faster
iteration" vs default "prefer better quality" skill) against Option B
(self-learning adaptive agent). Feasibility verdict is conditioned on the
perf investigation root cause (Livepeer orchestrator/GPU capacity): a skill
can bias model/settings/throughput and stream previews but cannot create
capacity. Includes the two-mode lever matrix mapped to exact MCP params,
one-file preference-memory design, A-vs-B tradeoff table, phased MVP->full
recommendation, and metrics/test plan reusing the perf harness.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(skills): add storyboard-perf-mode two-mode perf skill (Option A MVP)

Implements Phase 0 (route-around + measure) and Phase 1 (Option A MVP) from
STORYBOARD-PERF-SKILL-PROPOSAL.md: explicit prefer-quality (default) /
prefer-fast modes with a remembered preference, a lever matrix mapping each
mode to exact user-storyboard MCP tool + params, warm-cap i2v routing
(pixverse-i2v, never seedance-i2v-fast), session_id tagging, and measurement
hooks via get_perf_report / get_cost_report. Phase 2 (self-learning) is
intentionally not built.

Preference memory: ~/.storyboard/perf-preference.json via scripts/perf_pref.py
(get/set/reset). Skill lives under repo skills/ (committable) since .cursor/ is
gitignored; activation note included.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(perf): add Storyboard PR #685 post-fix E2E assessment

Ship-and-verify report for the seedance-i2v-fast → pixverse-i2v fast-animate
re-route (PR #685, merged 951eb7e0). Live head-to-head: i2v fast path
~33%→100% success, ~176-181s→~40s p50, ~2x cheaper per delivered asset.
Notes deploy status (merged; prefer_fast path pending redeploy) and spend (~$2.01).

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(billing): add per-unit (per-ticket) metering design proposal

Investigates the signer -> OpenMeter -> pymthouse metering pipeline and
documents that per-unit metering is not implemented today: cost is a
fee-floor (1 uUSD ceil) over a seconds-as-flat-unit quantity, so image
megapixels, video seconds, and TTS chars all meter identically.

Proposes a minimal 3-hop fix: add billing_unit_kind + billing_unit_quantity
to the create_signed_ticket event (unit from the cap price row, quantity
from the request payload), carry them through the collector, add a
usage_units SUM meter grouped by unit_kind, and compute pymthouse cost as
quantity x per-unit price reconciled against the network fee. Includes
per-unit requirement matrix, schema, phased backward-compatible rollout,
test plan, and owners.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: network pricing/metering/billing architecture across agent, byoc signer, live-runner

Add NETWORK-PRICING-ARCHITECTURE.html: a code-grounded examination of pricing
across the agent (user-facing USD), the byoc-staging-1 signer (on-chain tickets),
and the live-runner orchestrator, plus an extensible one-orch->many-runners design.
Builds on/reconciles the prior per-unit metering, BYOC->live-runner migration, and
signer-routing artifacts with fresh file:line evidence, a per-cap pricing config
schema, and the agent-vs-on-chain (single-source-of-truth) recommendation.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): consolidate to descriptor price segment as single source of truth

Establish the capability descriptor's offering.price as the ONE source of
truth for per-cap price + unit; demote price.json/pricing-table-deploy.json
to a build-time generated artifact. Add Part 0.5 (schema quote, field-by-field
gap table, consumer table, consolidated flow diagram, DO/DONT), reconcile the
Part 1 agent-pricing diagram and Part 4b config example, and flag the unit_kind
(+ quantity_source, price_scaling) gaps the PriceSchema must add to fully
replace price.json.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): add PR-cycle execution plan + design-review section

Add PRICING-EXECUTION-PLAN.html: 10 self-contained, flag-gated
(default OFF), observe->enforce PRs with per-PR test / prod-validation /
rollback / owner, the reconcile-by-construction invariant, a
gap-closure matrix, phased rollout, and end-to-end prod validation.
Append a concise "Design review findings + execution plan" section to
NETWORK-PRICING-ARCHITECTURE.html linking the plan, stating the
invariant, and listing the dead-code-removal tasks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): append independent code-verified review to execution plan

Fresh-eyes review of PRICING-EXECUTION-PLAN.html, verified against source
in storyboard-a3 and livepeer/go-livepeer. Verdict: NEEDS-REWORK with 4
blockers (invariant scaling term vs pixels_per_unit, lossy descriptor-as-
source vs pricing-table.json margin/tier model, closed unit_kind enum drops
live `tokens`, PR9 removing static-pricing.json fallback) plus 2 majors and
minors. Architecture/sequencing sound; fixes are bounded.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): add A/B/C fee-locus assessment to NETWORK-PRICING-ARCHITECTURE

Append section 7 "Where should fee/quantity compute live? (A vs B vs C)":
per-fact (price/quantity/fee) layer-knowledge table grounded in
remote_signer.go, orchestrator.go and gateway byoc.py; the on-chain
trust/consistency analysis (ExpectedPrice vs orch re-derivation, #3993);
the pre- vs post-inference metering point; and the verdict — hybrid of
A (signer derives fee, gateway reports quantity) + the price-config half
of C (runner owns per-unit price in its descriptor). Reject B and full C.
PR4/PR5 stand unchanged. Additive edit only.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add scratch notes analyzing go-livepeer PR #3992 live pricing

Analyze what PR #3992 actually ships (decimal USD runner price with
unit={hour,720p}, signer type=live elapsed-seconds billing) vs the
assumed type=fixed per-request model. Maps billing unit_kinds to
coverage, confirms per-call/per-image still need the quantity design
(PR4/PR5) and that tokens (B3) remains the residual gap.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): consolidated rewrite resolving review blockers B1-B4/M1-M2 + fold #3992/compute-placement

Resolves the independent review's four blockers and two majors in-plan and folds in
the compute-placement verdict (hybrid A + price-config half of C) and the PR #3992
fixed/live-pricing analysis. Plan status moves NEEDS-REWORK -> APPROVE-able.

- B1: correct invariant to fee_wei = (price_per_unit/price_scaling) x pixels_per_unit x qty
  (verified vs convert.py:56-67); F4 no longer calls per-price scaling speculative.
- B2: state two SoTs in one direction (build-time pricing-table.json cost/margin/tier ->
  runtime descriptor); convert.py generates the descriptor price, does not "write back".
- B3: add tokens to unit_kind enum + extractors + parity matrix + E2E (audit: enum complete).
- B4: keep static-pricing.json runtime fallback; PR9 removes only duplicate authoring.
- M1: shared quantity-extractor spec + cross-language golden vectors (Py/Go/TS).
- M2: PR2 reconciles generate-registry.ts (CAP_REGISTRY_PRICING) second registry path.
- Compute-placement: gateway reports QUANTITY, signer derives FEE; ExpectedPrice==advertised
  guard + qty cross-check.
- #3992: adopt runner decimal-USD price schema (PR3) + signer type-branched fee (PR5/PR8);
  per-call/per-image ride quantity mechanism; capture live_payment_processor pixel bug and
  global-vs-per-cap max-price caveats as risks.
- Minor: verified sanitizeUsageLabel real (:383), mint helper absent from product code;
  refreshed signer line cites.
- Architecture doc: minimal consistency edits (tokens row, #3992 pointer, SoT direction).

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): add §8 — Storyboard-independent PRs, regression class, and upstream already-exists vs still-needed recon

Additive section to PRICING-EXECUTION-PLAN.html documenting which pricing PRs
Storyboard can ship entirely within livepeer/storyboard (PR1/PR2 NO-REGRESSION,
PR10 low display-only risk, PR9 upstream-gated by PR3), the standalone payoff,
and a verified go-livepeer/gateway already-exists vs still-needed table
(ja/live-runner #3938, ja/live-pricing #3992, byoc-staging-1, lr-orch).

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add upstream pricing scope for owners (John/Josh/Rick)

PR-format scope doc from the agent's POV covering the three upstream
changes needed to close pricing end-to-end: go-livepeer PR3/PR5/PR8
(orch aggregation + signer stamp + fee-from-quantity), python-gateway
PR4 (payload->quantity), pymthouse PR6/PR7 (usage_units meter + cost).
Includes per-owner "already exists, don't rebuild" callouts, the
reconciliation invariant, and cross-owner ordering.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(pricing): add PRICING-DELIVERY-SUMMARY.html

Skimmable delivery summary of the pricing/billing/perf effort with
gh-verified status per artifact: what's shipped/built/merged vs open,
expected value per item, and the upstream PRs + infra gates left for
Josh/Rick/John. Corrects #430 to OPEN (not merged).

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin/developer-api Developer API plugin scope/shell Shell app changes size/L Large PR (201-500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants