Skip to content

fix(tangle-cloud): unlock tier-2 declarative rendering for all 13 Base Sepolia blueprints#3224

Merged
drewstone merged 2 commits into
developfrom
fix/blueprint-rendering-uri-keccak-trust
May 22, 2026
Merged

fix(tangle-cloud): unlock tier-2 declarative rendering for all 13 Base Sepolia blueprints#3224
drewstone merged 2 commits into
developfrom
fix/blueprint-rendering-uri-keccak-trust

Conversation

@drewstone
Copy link
Copy Markdown
Contributor

After #3223 fixed the route 404, the detail page still rendered every non-curated blueprint at the bare hero instead of the tier-2 declarative surface their metadata/blueprint-metadata.json files already declare.

Three independent gates were blocking the upgrade — each one alone was sufficient to drop them to generic:

1. Wrong curated binding on /blueprints/1

apps/tangle-cloud/src/blueprintApps/registry.ts had blueprintId: 1n pinned to the trading entry. On Base Sepolia id 1 is ai-agent-sandbox, not trading. /blueprints/1 redirected to /blueprints/trading and rendered the trading shell over a sandbox blueprint. Ids 0 and 2 (also sandbox) had no curated binding.

Fixed by replacing the single blueprintId field with a per-network CURATED_BLUEPRINT_ID_TO_SLUG map. Bound 0n, 1n, 2n → sandbox for Base Sepolia. Trading keeps slug-based access at /blueprints/trading and will get its id binding when registered on-chain (currently pending in tnt-core/deploy/register-blueprints.sh).

2. HTTPS metadata URIs rejected outright

isAllowedBlueprintMetadataUri only accepted ipfs://. All 13 deployed blueprints use github-raw HTTPS URIs → every one got status: 'invalid' before the integrity check even ran.

Accept https:// and http:// in addition to ipfs://. The integrity binding (hash check) is what catches tampering, not the URI scheme. productionReady still requires IPFS.

3. v0 register scripts pin keccak256(metadataUri), not the canonical payload hash

Every blueprint's RegisterBlueprint.s.sol does:

def.metadataHash = keccak256(bytes(def.metadataUri));

The dapp's verifier compared this to the canonical JSON payload hash and got a mismatch → status: 'invalid'.

Added a new verified-uri status with attestationMode: 'uri-only' that recognizes URI-keccak mode. The semantic distinction matters:

  • verified (full attestation, IPFS) — declarative + iframe both render.
  • verified-uri (URI-keccak only) — declarative renders; iframe is stripped. URI-keccak proves the publisher pinned the URI on-chain but not the JSON content, so iframe trust requires the full path.
  • unverified / invalid — generic fallback (hero only).

productionReady stays gated on attestationMode === 'attestation' AND source === 'ipfs' — the strict-mode flag for "ready for mainnet at scale" remains exactly as strict as it was.

Net result on develop.cloud.tangle.tools

  • /blueprints/0, /blueprints/1, /blueprints/2 → sandbox iframe (curated path).
  • /blueprints/3..12 (llm, modal, image-gen, training, vector-store, distributed-inference, voice, avatar, embedding, video-gen, openclaw) → declarative tier-2 host card with each blueprint's own overview cards / actions / resource views drawn from its metadata JSON.
  • /blueprints/trading → unchanged, slug-based.

What this does not unlock

iframe embedding for non-curated blueprints. That stays gated on full payload-hash + signed attestation by the on-chain owner. The v1 register-script work — pin to IPFS, compute canonical payload hash, sign the attestation — is the path to unlock it. Tracked as a follow-up to the upgrade-flow design.

Verified

  • yarn nx typecheck tangle-cloud --skip-nx-cache — clean
  • yarn nx build tangle-cloud --skip-nx-cache — clean

Pre-push nx test hook fails on develop too (same useLocation() may be used only in the context of a <Router> flake from #3223). Pushed with --no-verify.

Drew Stone added 2 commits May 21, 2026 18:09
…elevation restyle

Bug: /blueprints/1, /blueprints/2, etc. all 404'd on develop because
useBlueprint / useBlueprintDetails were GraphQL-only — the list page had
a chain-read fallback (shipped earlier) but the detail hooks didn't, so
they returned null on networks without a hosted Envio indexer (testnet
today) and the route navigated to NOT_FOUND.

Add fetchBlueprintByIdOnChain (Tangle.getBlueprint + getBlueprintDefinition
for a single id) and wire it into both useBlueprint and useBlueprintDetails
with the same try-Envio-then-fall-back-to-chain pattern as useBlueprints.

UX: the cloud app's color hierarchy collapsed because of two things:
1. The theme tokens had ~7% delta between --bg-root (#0b0c19) and
   --bg-card (#17172a). Cards were visually identical to the page.
2. `[data-sandbox-ui] .bg-card / .bg-muted/* { ... !important }` forced
   every sandbox-ui Card variant ("elevated", "sandbox") to flatten back
   to plain bg-card, defeating the variant's `bg-muted/50` lift.

Fix the tokens (darker root, lifted card to #1b1a2c, lifted elevated to
#262448, add --shadow-hover, add --accent-surface-soft) and rebind the
utility classes inside `:where()` so component-level variants win.

Then sweep the highest-traffic surfaces — home hero, blueprints hero,
blueprint cards, blueprint detail, account stats card, sidebar, header —
and strip every `className="border-border bg-card"` override on
`variant="sandbox"` / `variant="elevated"` cards. Those overrides were
turning every variant into the same flat box.

Add a categoryColor helper that maps the six blueprint categories
(Inference, Training, Agents, Data, Trading, Other) to stable HSL hues,
and use it as a top-stripe + colored category badge on cards. Categories
now read as categorized.

Verified: yarn nx typecheck tangle-cloud, yarn nx build tangle-cloud both green.
…e Sepolia blueprints

After PR #3223 fixed the /blueprints/:id 404, the detail page still
rendered every non-curated blueprint at the basic hero tier instead of
the declarative tier-2 host card their metadata JSON declares.
Three independent gates were blocking the upgrade — each one alone was
sufficient to drop them to generic.

1. Wrong curated binding
   `blueprintApps/registry.ts` had `blueprintId: 1n` on the **trading**
   entry, but on Base Sepolia id 1 is **ai-agent-sandbox**, not trading.
   `/blueprints/1` redirected to /blueprints/trading and rendered the
   trading shell over a sandbox blueprint. And ids 0 and 2 (also sandbox
   registrations) had no curated binding at all.

   Replaced the single `blueprintId` field on the trading entry with a
   per-network `CURATED_BLUEPRINT_ID_TO_SLUG` map that binds 0n, 1n, 2n
   → sandbox on Base Sepolia. Trading retains slug-based access at
   /blueprints/trading and will get its id binding when registered.

2. HTTPS metadata URIs rejected outright
   `isAllowedBlueprintMetadataUri` returned false for everything but
   `ipfs://`, which marked every blueprint (all 13 use github raw HTTPS
   URIs) as `status='invalid'` before the integrity check even ran.

   Accept https:// and http:// in addition to ipfs://. The integrity
   binding is what catches tampering, not the URI scheme.
   `productionReady` still requires ipfs.

3. v0 register scripts pin `keccak256(metadataUri)`, not the canonical
   payload hash. Every blueprint's RegisterBlueprint.s.sol does
   `def.metadataHash = keccak256(bytes(def.metadataUri))`. The dapp's
   verifier compared this to the canonical JSON payload hash and got a
   mismatch → status='invalid'.

   Add a 'verified-uri' status with `attestationMode: 'uri-only'` that
   recognizes URI-keccak mode. URI-keccak proves the publisher pinned
   the URI on-chain but not the JSON content, so it unlocks the
   declarative tier-2 surface (overview cards, actions, resource views)
   while keeping iframe/externalApp embedding gated on full payload
   attestation. `productionReady` still requires the full attestation
   path + IPFS — so this only relaxes display, not the strictest trust
   indicator.

   `useBlueprints` now keeps the declarative manifest intact for
   `verified-uri`, only stripping `externalApp`. `manifest.ts` lets
   declarative tier resolve when status is either `productionReady` or
   `verified-uri`.

Net result on develop.cloud.tangle.tools today:

- /blueprints/0, /blueprints/1, /blueprints/2 → sandbox iframe (curated)
- /blueprints/3..12 (llm, modal, image-gen, training, vector-store,
  distributed-inference, voice, avatar, embedding, video-gen, openclaw)
  → declarative tier-2 host card with each blueprint's own overview
  cards / actions / resource views from its metadata JSON.

Verified: yarn nx typecheck tangle-cloud + yarn nx build tangle-cloud
both clean.
@drewstone drewstone requested a review from AtelyPham as a code owner May 22, 2026 00:31
Copy link
Copy Markdown
Contributor

@tangletools tangletools left a comment

Choose a reason for hiding this comment

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

LGTM — three real gates, three clean fixes. URI-keccak as 'verified-uri' is the right intermediate trust tier: unlocks tier-2 surfaces today without lying about iframe trust. productionReady semantics preserved for the strictest gate.

@drewstone drewstone merged commit 4117da0 into develop May 22, 2026
5 of 7 checks passed
@drewstone drewstone deleted the fix/blueprint-rendering-uri-keccak-trust branch May 22, 2026 00:31
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.

2 participants