Skip to content

Add Product CDM runtime adapter - #110

Merged
knzeng-e merged 4 commits into
devfrom
feat/product-cdm-runtime-adapter
Aug 3, 2026
Merged

Add Product CDM runtime adapter#110
knzeng-e merged 4 commits into
devfrom
feat/product-cdm-runtime-adapter

Conversation

@knzeng-e

@knzeng-e knzeng-e commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Outcome

Adds an experimental Product CDM/PAPI runtime adapter behind Dotify's new RuntimeReadPort / RuntimeWritePort boundary.

The adapter maps the existing Dotify SmartRuntime method surface to Product SDK contract-handle style query / tx calls, validates CDM package address mismatches, returns Product transaction hashes, and fails explicitly for unsupported Product runtime history reads. It is not selected by the shipped UI yet.

Issue and context

Refs #85.

Stacked on #109, which extracts the runtime ports. This PR is the next Product portability step after that boundary exists.

Local scope docs:

  • docs/backlog/polkadot-product-readiness-and-killer-dapp-roadmap.md
  • docs/explanation/product-devnet-architecture.md
  • docs/explanation/architecture-overview.md
  • docs/operations/product-devnet-deployment.md

Official Product docs now describe CDM as the Product contract package model: contracts are deployed to Product DevNet Asset Hub through pallet-revive, registered by package name, installed into a frontend through cdm.json, and consumed with @parity/product-sdk-contracts handles. Dotify's current deployed runtime remains viem/EVM, so the safe next step is an adapter that can consume those CDM handles without wiring it into user flows before a real Dotify CDM manifest exists.

References:

Architecture and key concepts

flowchart LR
  Hooks[Catalog + Artist hooks] --> Ports[RuntimeReadPort / RuntimeWritePort]
  Ports --> Viem[ViemRuntimeAdapter]
  Ports --> Product[ProductCdmRuntimeAdapter]
  Product --> Resolver[CDM contract resolver]
  Resolver --> Manager[ContractManager / cdm.json packages]
  Resolver --> RuntimeFactory[Runtime ABI bound to artist runtime address]
  Manager --> PAPI[Product SDK contracts / PAPI / pallet-revive]
Loading

The adapter has three layers:

  • ProductCdmRuntimeContractResolver: resolves directory, factory, and dynamic artist runtime handles.
  • createProductCdmRuntimeReader: maps reads such as runtimeOf, artistsPage, musicRegGetTrack, musicAccCanAccess, and pendingRuntimeStageOf.
  • createProductCdmRuntimeWriter: maps writes such as createRuntime, installRuntimeStep, musicRegRegister, musicRoyPayAccess, musicRegSetAccessMode, and release activation/deactivation.

The resolver reflects CDM's package model. Directory and factory can be package-resolved static contracts. Artist runtimes are dynamic instances that share a SmartRuntime ABI, so the adapter requires an explicit runtimeContractFactory(runtimeAddress, runtimePackage).

How it works

The adapter accepts structural Product contract handles compatible with the Product SDK contracts API:

  • .query(...) returns { success, value };
  • .tx(...) returns a Result carrying a Product SDK transaction result with txHash.

Queries normalize the same values the viem adapter returns to the hooks:

  • zero-address runtime results become null;
  • directory pages are paginated and zero-address runtimes are skipped;
  • runtime track snapshots include royalty splits;
  • unreadable split rows are skipped without failing the whole runtime catalog.

Transactions return the SDK txHash as Dotify's existing Hash type. waitForTransaction is a no-op because Product SDK .tx() already signs, submits, and watches before resolving.

Royalty payment history deliberately throws ProductCdmRuntimeUnsupportedOperationError. The current Product contract handle surface does not replace viem's historical getLogs call. Product mode must use the backend catalog/read-model indexer, or a future Product event/indexer API, for that artist-console history.

Design decisions and tradeoffs

The adapter is present but not selected by default. That keeps standalone Netlify/Fly behavior and the Product DevNet baseline stable while giving the next PR a concrete integration target once cdm.json and generated types exist.

Alternatives considered:

  • Wire Product writes immediately: rejected because Dotify has no CDM-installed Product runtime packages yet and no real host-signed transaction smoke evidence.
  • Pretend royalty logs are available through contract queries: rejected because it would hide a real Product API gap.
  • Replace viem adapter types with Product SDK types globally: rejected because standalone EVM remains the public runtime path.

Security, failure, and operations

Security invariants preserved:

  • No Product account is accepted as an EVM signer.
  • No backend key-delivery signature scheme changes are introduced.
  • No frontend secrets or hidden signers are introduced.
  • CDM package/address mismatches throw instead of silently using the wrong contract.
  • Missing methods, failed queries, rejected transactions, and invalid transaction hashes fail explicitly.

Operationally, there are no new Netlify, Fly, or Product environment variables in this PR. To actually enable this adapter later, operators still need CDM-deployed Dotify runtime packages, cdm.json, generated contract types, pallet-revive account mapping, Bulletin authorization, and real Product host transaction smoke evidence.

Review guide

Suggested order

  1. web/src/features/runtime/productCdmRuntimeAdapter.ts - verify the adapter implements the runtime ports without selecting Product mode by default.
  2. web/src/features/runtime/productCdmRuntimeAdapter.test.ts - verify method routing, failure behavior, zero-address normalization, split fallback, and transaction hash handling.
  3. docs/explanation/product-devnet-architecture.md - verify the docs do not overclaim Product write readiness.
  4. docs/backlog/polkadot-product-readiness-and-killer-dapp-roadmap.md, docs/backlog/README.md, README.md, spec.md, docs/index.html, and docs/operations/product-devnet-deployment.md - verify roadmap and operator wording stays aligned.

Verify carefully

  • Is the dynamic runtime-instance factory explicit enough for artist-owned SmartRuntimes?
  • Do package/address mismatches fail closed?
  • Does .tx() error handling reject SDK errors, dispatch failures, and invalid hashes?
  • Does the adapter avoid becoming active before CDM packages and host signing evidence exist?
  • Is the royalty history limitation documented honestly?

Validation

Evidence What it proves
cd web && npm run test:unit -- --run src/features/runtime/productCdmRuntimeAdapter.test.ts src/features/runtime/viemRuntimeAdapter.test.ts Focused runtime adapter tests cover Product CDM and viem port behavior.
cd web && npm run lint ESLint has 0 errors; 3 existing React hook dependency warnings remain in App.tsx and ArtistShell.tsx.
cd web && npm run test:unit 29 frontend test files / 194 tests pass, including Product CDM adapter coverage.
cd web && npm run build The standard standalone build compiles with the new adapter module present.
cd web && npm run build:product-devnet The Product DevNet build compiles with the new adapter module present.
cd web && npm run fmt:check Frontend source and checked README formatting pass after Prettier.
git diff --check No whitespace errors in the final diff.
node scripts/backlog-sync.mjs --check --offline Backlog sync passes; existing warnings remain for active item 24 without GitHub mapping and duplicate backlog doc 08.

Known limitations and follow-ups

This PR should remain Refs #85, not Closes #85.

Remaining before #85 can close:

  • wire a real cdm.json manifest and generated Product contract types into Product mode;
  • deploy/register Dotify runtime packages through CDM on Product DevNet;
  • run real host-signed transaction smoke tests;
  • add backend Product signature-scheme verification and address binding before protected key delivery;
  • prototype Product resource allocation;
  • prototype bounded Statement Store presence;
  • attach real Product host/Desktop/Web smoke evidence after operator deployment.

Metadata checklist

  • Backlog issue linked with correct close/reference semantics: Refs [Product SDK][P1] Prove Product host compatibility before integration #85
  • Local backlog document linked
  • Added to Project 5 (Dotify sprints)
  • Project Priority, Track, Phase, Type, and Backlog doc mirror the issue
  • Workflow status matches draft/review state
  • Assignee set: knzeng-e
  • Applicable labels set: dotify-backlog, product-sdk
  • Applicable milestone set, or confirmed none exists
  • Reviewers requested when ownership is known
  • Draft/ready state is intentional

@knzeng-e knzeng-e added dotify-backlog Tracked by docs/backlog/backlog.json and Project 5 product-sdk Polkadot Product SDK / Host / Playground integration labels Jul 26, 2026
@knzeng-e knzeng-e self-assigned this Jul 26, 2026
@knzeng-e knzeng-e moved this from Todo to In Progress in Dotify sprints Jul 26, 2026
@knzeng-e
knzeng-e changed the base branch from feat/product-runtime-ports to dev August 3, 2026 13:33
@knzeng-e
knzeng-e marked this pull request as ready for review August 3, 2026 13:33
@knzeng-e
knzeng-e merged commit c8dcf0c into dev Aug 3, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Dotify sprints Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dotify-backlog Tracked by docs/backlog/backlog.json and Project 5 product-sdk Polkadot Product SDK / Host / Playground integration

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant