Skip to content

Migrate curator preflights to chain-authoritative ContextGraphs.isAuthorizedPublisher #375

@branarakic

Description

@branarakic

Context

PR #299 added a curator-only preflight to /api/shared-memory/publish (using agent.assertContextGraphOwner) to close the 200/tentative masked-failure where unauthorized publishes silently succeeded locally and only later reverted on-chain.

Codex review on #299 (thread 1, thread 2, thread 3) and earlier replies on the same PR pointed out a real but explicitly-scoped gap: the preflight is stricter than the contract.

The gap

assertContextGraphOwner compares the caller against the locally stored dkg:curator wallet DID. The on-chain ContextGraphs.isAuthorizedPublisher is richer:

  • For PCA curators it live-resolves the NFT owner via ownerOf(accountId) rather than a stored snapshot.
  • It accepts any agent registered via agentToAccountId(...) for the PCA, not just the curator wallet.
  • It follows ownership changes after NFT transfer.

Today's local preflight therefore over-rejects:

  • PCA-delegated agents.
  • Post-transfer NFT holders whose wallets don't match the stale local curator metadata.

The same shape of check is in use by share, invite, rename, and the manifest-publish route, so this is a cross-cutting migration rather than a single-route fix.

Status of curated CGs today

The over-rejection is observable but bounded — PCA mode is not exercised on testnet yet, and the local-curator metadata matches the on-chain owner for every CG that's been registered through dkg context-graph register. PR #299 still nets a strict improvement over HEAD: the prior 200/tentative masking was always wrong; the new 403 is correct in every case except the PCA edge.

Proposed work

  1. Add chain.isAuthorizedPublisher(contextGraphId, callerAddress): Promise<boolean> to ChainAdapter (already exists as a Solidity entry point on ContextGraphs.sol).
  2. Replace the local assertContextGraphOwner preflight in:
    • packages/cli/src/daemon/routes/memory.ts (/api/shared-memory/publish)
    • packages/cli/src/daemon/routes/context-graph.ts (share, invite, rename, manifest-publish)
  3. Drop or relegate assertContextGraphOwner to administrative routes that legitimately want owner-only semantics (vs broader publish auth).
  4. Add the daemon-level integration test Codex requested on fix(cli): gate /api/shared-memory/publish on curator identity #299 thread 3 — covering one open CG (no preflight, fall-through), one curated EOA-curator CG (curator wallet 200, non-curator 403), one PCA-curated CG (NFT owner 200, registered agent 200, non-registered agent 403). Real-Hardhat daemon-http-behavior-extra.test.ts model.

Out of scope here

Open-CG publishes (publishPolicy = EVM_PUBLISH_OPEN) are unaffected — they don't go through the curator preflight in either world.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions