feat(pymthouse): builder-sdk 0.6.0 and RFC 8693 API key exchange#424
Conversation
…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.
|
|
Replace local file: links so CI/Vercel can resolve the published package.
There was a problem hiding this comment.
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-sdkfrom0.5.0→0.6.0across app + developer-api plugin, and updatepackage-lock.jsonaccordingly. - 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.
|
Deployment failed with the following error: |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Composite keys can be presented as Bearer; bare pmth_* must be exchanged first.
📝 WalkthroughWalkthroughPymtHouse 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. ChangesPymtHouse API-key flow
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
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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
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. Comment |
There was a problem hiding this comment.
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 winDefensively 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
nullinstead of an object,typeof body === 'object'remains true. Subsequent access to properties likebody.error_descriptionorbody.tokenwill throw aTypeErrorand crash the thread.Validating that the parsed response is a non-null, non-array object inside the
tryblock ensures that unexpected payloads safely trigger the genericPmtHouseErrorcatch 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!package-lock.json
📒 Files selected for processing (10)
apps/web-next/package.jsonapps/web-next/src/lib/billing/pymthouse-adapter.test.tsapps/web-next/src/lib/billing/pymthouse-adapter.tsapps/web-next/src/lib/pymthouse-client.test.tsapps/web-next/src/lib/pymthouse-client.tsapps/web-next/src/lib/pymthouse-signer-exchange-config.tsdocs/pymthouse-integration.mdplugins/developer-api/backend/package.jsonplugins/developer-api/frontend/package.jsonplugins/developer-api/frontend/src/pages/DeveloperView.tsx
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>
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>
…_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>
…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>
…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>
Summary
@pymthouse/builder-sdkto the published builder-sdk 0.6.0 contract.POST /api/v1/apps/{clientId}/oidc/token), replacing the old signer-session path.app_<24hex>_pmth_…keys as DMZ Bearer credentials; update adapter/client tests and PymtHouse docs accordingly.Test plan
@pymthouse/builder-sdkpymthouse-adapter/pymthouse-clientunit tests.Summary by CodeRabbit
Improvements
app_*_*and legacypmth_*presented API keys.Documentation