Skip to content

feat: harden production readiness and rebuild Dotify UX#92

Merged
knzeng-e merged 21 commits into
mainfrom
feat/dotify-thresholds-prod-readiness
Jul 14, 2026
Merged

feat: harden production readiness and rebuild Dotify UX#92
knzeng-e merged 21 commits into
mainfrom
feat/dotify-thresholds-prod-readiness

Conversation

@knzeng-e

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

Copy link
Copy Markdown
Owner

Summary

  • harden Dotify Thresholds production readiness around an attested artist-publication deployment
  • reopen artist runtime creation and release publication on the fresh audited Paseo factory/directory
  • fix local playback when the primary Paseo IPFS gateway is blocked by browser CORS by falling back across configured IPFS read gateways
  • keep Shared Score as the product structure and honesty model, then restore the Living Light presentation layer as a track-driven dark listening room
  • add the global aura stylesheet and wire the active track or public artist name into the app-wide aura engine
  • bring the Stage rail and Sky of Rooms back into the Now and Rooms surfaces without inventing fake playback or room activity
  • align the public page, README, design rationale, backlog, and operator/runbook docs with the active deployment and visual direction
  • keep the legacy registry-remediation tooling and docs for the old vulnerable deployment without reusing it for new publication

UX direction

Shared Score remains the IA and UX contract: Now, Rooms, contextual Player, You, and Studio keep the same low-friction product shape and truthful state rules.

The presentation is now the Living Light amendment: a deep navy canvas, glass chrome, electric cyan actions, restrained Polkadot pink, and web/src/styles/aura.css as the final stylesheet layer. applyAura() rewrites the --aura-* variables from the active track or artist context, so the field, hero, catalogue cards, player stage, dock, Stage rail, and Sky of Rooms respond to real product state rather than decorative fake motion.

Production status

Artist publication is open on the configured fresh Paseo deployment:

  • factory: 0x9337287a194dfd8b53939eee1890b3f4ec0f8b0d
  • directory: 0xda2761fea6f0871ed44ec719860fddb51b115be8
  • registry facet: 0x76ac102f448fbab9a7ea9efe4450878c01aabc8d
  • finalized audit block: 10904607
  • block hash: 0x7eacbb1e0ee963a8e732239990403c4836e56d64af8151b830eb341ba3c505af
  • corrected registry code hash: 0xa509d4ccc5206974069bb858faba07e42b1f7b9b3fd217adc7bb40a8f714d788

The read-only live audit verified the factory/directory pairing, the corrected registry facet hash, zero finalized runtimes, and zero pending runtimes. The previous deployment remains documented as legacy remediation evidence and must not be reused for new publication.

Validation

  • contracts/evm: npm run registry:audit:testnet -> passing on finalized block 10904607
  • web: npm run build -> passing after the Living Light update
  • web: npm run lint -> 0 errors; 3 existing hook-dependency warnings
  • web: npm run fmt:check -> passing
  • git diff --check -> clean
  • previous branch validation still applies: npm run test:unit -> 134/134, targeted IPFS gateway fallback test passing, targeted publication-safety tests 28/28, signaling 42/42, API 64/64, Playwright E2E 11/11, contracts 44/44

Notes

  • no production secrets or private keys are included
  • the PR remains draft while final review/preview checks complete

knzeng-e and others added 2 commits July 10, 2026 18:44
Backend key service:
- /health/ready readiness diagnostics: master-secret and Pinata config
  (booleans only), RPC reachability + chain ID match, artist directory
  readability, factory code presence; 503 when key delivery cannot work
- /version now reports the deploy commit SHA (GIT_COMMIT_SHA or git)
- request correlation IDs: x-request-id echoed or generated on every
  response and included in error bodies
- typed error envelope { error, code, requestId } from global error and
  404 handlers, registered before route plugins so encapsulated scopes
  inherit them; framework statuses (429, 400) no longer collapse to 500
- pino redaction for authorization/cookie headers and session-token/
  signature body fields
- app assembly extracted to src/app.ts so tests exercise real wiring

Signaling server:
- /health now echoes non-secret config: allowed origins, room TTL, host
  heartbeat timeout, per-room listener cap

Tests: health routes (ready 200/503, no secrets), app wiring (request-id
echo/generation, typed 404, preserved statuses), signaling health echo.
README documents how to inspect health; ticket 10 carries delivery notes
with the remaining frontend surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@netlify

netlify Bot commented Jul 12, 2026

Copy link
Copy Markdown

Deploy Preview for muzinga ready!

Name Link
🔨 Latest commit 0e3184d
🔍 Latest deploy log https://app.netlify.com/projects/muzinga/deploys/6a566070a5014f00087da3cd
😎 Deploy Preview https://deploy-preview-92--muzinga.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@knzeng-e knzeng-e changed the title feat: harden Dotify thresholds production readiness feat: harden production readiness and rebuild Dotify UX Jul 12, 2026
@knzeng-e knzeng-e self-assigned this Jul 12, 2026
@knzeng-e
knzeng-e marked this pull request as ready for review July 12, 2026 17:59
- Load public room summaries when the listener shell mounts.
- Resolve the room targeted by `#/rooms/<roomId>`.
- Present its host, work, real presence count, room code, and wallet-free
promise in the existing join dialog.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Seem too verbose to me add the "wallet-free" promise in the join dialog

- Present its host, work, real presence count, room code, and wallet-free
promise in the existing join dialog.
- Preserve the deliberate first-time pseudonym step and remembered-name
auto-join behavior.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

We should strengthen this behavior to allow several different users to use the same device, and have their access/labeling. Maybe bind personhood to the triangle host

attested factory/directory.
- The publish form keeps the artist wallet as the primary rights holder and lets
the artist add collaborators, producers, labels, or other EVM addresses with
basis-point shares.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

investigate if we should change the basis-points for percentage. Does it make sense for the music industry ? For users, this should remain quite intuitive

### Security hardening

- Runtime-owner-only track registration plus outsider test.
- Server-side BLAKE2b-256 verification of uploaded audio plus mismatch test.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Need to elaborate why this additional verification is a must to have in the current context

@knzeng-e

Copy link
Copy Markdown
Owner Author

@claude please carefully review this PR

@claude

claude Bot commented Jul 14, 2026

Copy link
Copy Markdown

Claude finished @knzeng-e's task in 7m 1s —— View job


Review: harden production readiness and rebuild Dotify UX

  • Gather context (PR body, CLAUDE.md, changed files)
  • Review services/api (auth, keys, sessionTokens, replayProtection, signatures, uploads, diagnostics, health, config, logger)
  • Review contracts/evm (registry upgrade tooling, unsafe mock, tests)
  • Review web/ (deploymentSafety, useArtistConsole, useSession, JoinRoomModal, signaling)
  • Cross-check deployment addresses across fly.toml, deployments.json, web config, docs
  • Synthesize findings

This is a large, mostly well-executed PR. The core security fix (owner-guard on musicRegRegister) is correctly ordered and well-tested, the session/nonce/signature spine in services/api is fail-closed throughout, and the signaling authorization fix closes a real cross-room relay hole. One deployment-config finding below is high severity and should block merge until resolved.

High severity

services/api/fly.toml points production at the legacy vulnerable deployment, not the fresh attested one.
This PR's entire safety story is "artist publication only happens on the fresh audited factory/directory (0x9337287a... / 0xda2761fea...)" — enforced client-side by web/src/shared/config/deploymentSafety.ts's registryOwnerGuardAttestation, and reflected in deployments.json, web/src/shared/config/deployments.ts, and README.md. But services/api/fly.toml changes DOTIFY_FACTORY_ADDRESS/DOTIFY_DIRECTORY_ADDRESS to 0x824ea33000e5e2ca9ddad030befa7331b38c41ce / 0x7f90d15b5ec5f3a668e4dc14def3fe1c876dde0c — which docs/operations/registry-facet-remediation.md itself labels "Legacy factory/directory" with "2 finalized runtimes, both still vulnerable" and "an outsider eth_call can still simulate a successful registration."

services/api/src/services/chainAccess.ts (findOwningRuntimes, line ~124) and services/api/src/services/diagnostics.ts read DOTIFY_DIRECTORY_ADDRESS/DOTIFY_FACTORY_ADDRESS directly to resolve which SmartRuntime owns a track and to run readiness checks. As configured, the deployed backend's content-key access checks would run against the known-vulnerable directory while the frontend's publication guard is quarantining against a different (safe) one — the two halves of the production spine would be pointed at different deployments.

Fix this →

Medium severity

Registry upgrade tooling: negative-path tests are missing for the most safety-critical guardrails. contracts/evm/tasks/registryUpgrade.ts implements solid fail-closed gates (deployed-code-hash verification instead of trusting addresses, a --confirm-plan digest binding chain/owner/facet/catalogue state, owner-is-a-contract refusal, signer-not-owner refusal, post-upgrade re-verification). But contracts/evm/test/RegistryUpgradeTasks.test.ts only exercises the happy path — none of --confirm-plan mismatch, target facet code-hash mismatch, signer-not-owner, owner-is-a-contract, or assertOutputPathAvailable rejecting an existing --out path are covered. registry:deploy-facet (the task that broadcasts a real deployment tx) has zero test coverage at all. Given this tooling exists specifically to remediate an already-exploited vulnerability, the negative paths are exactly what should be pinned down by tests before this is trusted for the next remediation cycle.

Fix this →

Low severity / notes

  • CLAUDE.md's "Active ticket" section (lines 59-63) is stale. It still points to Sprint 1 Ticket 05 (classic-unlock e2e), but this PR's actual scope is Ticket 25 (docs/backlog/25-thresholds-functional-v1.md) plus tickets 04/10 and a new out-of-ticket remediation runbook. Worth updating so the pointer matches what's actually being delivered, per the file's own "Implementation discipline" rule.
  • web/src/hooks/useArtistConsole.ts: refreshArtistRuntime() uses artistRegistrationConfigured rather than the publication-quarantine flag, so it still performs a read-only runtimeOf lookup while publication is quarantined. Harmless today (read-only), but worth a comment so a future edit doesn't silently graduate it into a write path.
  • contracts/evm/tasks/registryUpgrade.ts: getReadContract returns Promise<any>, losing type safety on all read calls in an otherwise carefully typed file.

What looks solid

  • MusicRegistryPallet.sol: LibDiamond.enforceIsContractOwner() is the first statement in musicRegRegister — correct ordering, matches the PR's stated fix.
  • services/api auth/session/key spine (signatures.ts, sessionTokens.ts, replayProtection.ts, chainDomain.ts, keys.ts): consistently fail-closed, chain-ID bound, nonce consumed only after signature check, session tokens HKDF-derived and constant-time verified, no secrets in logs (logger.ts redaction) or health/diagnostics output.
  • web/src/shared/config/deploymentSafety.ts + useArtistConsole.ts: publication guard fails closed on any unresolved/mismatched attestation input and is checked before any wallet/chain write.
  • web/server/signaling.mjs: routePeerMessage now validates room/role membership before relaying WebRTC signaling — closes a real cross-room injection/eavesdropping gap, with test coverage for the denial paths.
  • services/api/src/routes/uploads.ts: server-side BLAKE2b-256 verification of uploaded audio against the claimed contentHash before it can influence key derivation or storage.
  • No curly/smart quotes introduced in any code file (checked the full diff).

No other correctness, security, or CLAUDE.md-compliance issues found across the remaining docs/style/UI-only changes (docs/index.html, web/src/styles/*, spec.md, reference docs).

@knzeng-e
knzeng-e merged commit a1fcbd5 into main Jul 14, 2026
10 checks passed
@knzeng-e
knzeng-e deleted the feat/dotify-thresholds-prod-readiness branch July 14, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contracts documentation Improvements or additions to documentation enhancement New feature or request frontend observability P0 refactor tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant