Skip to content

feat: graph-native attestation IRI + MsgAttest broadcast#21

Open
DarrenZal wants to merge 1 commit into
regen-prodfrom
feat/graph-iri-msgattest
Open

feat: graph-native attestation IRI + MsgAttest broadcast#21
DarrenZal wants to merge 1 commit into
regen-prodfrom
feat/graph-iri-msgattest

Conversation

@DarrenZal
Copy link
Copy Markdown
Contributor

Summary

  • Graph-native attestation IRIs: JSON-LD attestation documents with inline @context → URDNA2015 canonicalization → BLAKE2b-256 → base58check → regen:*.rdf graph IRI. Mirrors the TypeScript implementation in regen-server.
  • MsgAttest broadcast: New POST /claims/{rid}/attestations/{att_rid}/attest-onchain endpoint using regen tx data attest (identity-bound) instead of regen tx data anchor (timestamp-only). Existing MsgAnchor path is untouched.
  • RBAM integration design doc: Two-tier model — pilot uses direct Keplr signing, later adds org-level delegation via DAO DAO / RBAM roles matching the Marketplace pattern (can_anchor_attest_data).

Key files

File What
api/ledger_anchor.py generate_graph_iri(), broadcast_attest(), build_attestation_jsonld(), base58check encoding
api/routers/claims_router.py POST /attest-onchain endpoint + response models
requirements.txt pyld>=2.0.4 (URDNA2015 canonicalization)
tests/test_graph_iri.py 19 new tests
docs/claims/rbam-integration.md RBAM integration design doc (327 lines)

Context

Based on Marie's architecture corrections in Telegram (Mar 26–Apr 2):

  1. JSON-LD data must be anchored as graph data, not raw data — MsgAttest requires ContentHash.Graph
  2. Use Regen Roles / DAO DAO / RBAM for org-level reviewer authorization, not raw cosmos.authz
  3. Reference implementation: useCreateDao

Open questions for Marie

  1. RBAM contract addresses on mainnet/testnet?
  2. Minimal DAO setup path for testing (skip full org creation)?
  3. Can we query RBAM role membership from the backend?
  4. Recommended testnet for Phase 3 development?

Test plan

  • 19 new tests pass (graph IRI gen, base58 encoding, MsgAttest broadcast mocks)
  • 59 existing tests still pass (no breakage)
  • Marie: review graph IRI byte layout matches regen-server contentHashGraphToIRI
  • Marie: review inline @context pattern vs FWG context dereference
  • End-to-end testnet broadcast (blocked on testnet selection)

🤖 Generated with Claude Code

Implements graph-native attestation path per Marie's architecture corrections:
- JSON-LD attestation documents with inline @context (no remote URL fetch)
- URDNA2015 canonicalization → BLAKE2b-256 → base58check → regen:*.rdf IRI
- MsgAttest broadcast endpoint alongside existing MsgAnchor path
- RBAM integration design doc for org-level reviewer authorization
- 19 new tests (78 total, all passing)

New endpoint: POST /claims/{rid}/attestations/{att_rid}/attest-onchain
New dep: pyld>=2.0.4

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@DarrenZal
Copy link
Copy Markdown
Contributor Author

Hi Marie — thanks for your Telegram feedback (Mar 26–Apr 2) that shaped this entire PR.

What to review first:

  1. api/ledger_anchor.pygenerate_graph_iri() specifically. This mirrors contentHashGraphToIRI in regen-server. The key question is whether the URDNA2015 canonicalization + BLAKE2b-256 + base58check path here matches what regen-server expects. If those byte-level details diverge, attestation IRIs won't match cross-system.
  2. The @context approach in build_attestation_jsonld() — we inline the context rather than dereference an FWG URL. Is that acceptable for V2 or do we need context dereference?

Explicitly out of scope for this PR:

The four open questions at the bottom of the PR description are the main things I need from you — especially the RBAM contract addresses and minimal DAO setup path. Happy to pair on any of it.

@blushi
Copy link
Copy Markdown

blushi commented Apr 15, 2026

Responses to open questions:

  1. testnet: https://github.com/DA0-DA0/dao-dao-ui/blob/development/packages/utils/constants/codeIds.json#L1805-L1829
    mainnet: https://github.com/DA0-DA0/dao-dao-ui/blob/development/packages/utils/constants/codeIds.json#L1778-L1802
    But is this a user specification to support org from the start or not? I think the user flows should probably be a bit more specified before digging into the implementation...

  2. At least, you need to create a DAO with RBAM as part of its proposal modules to support roles based permissions, otherwise DAO members can only submit proposals and vote on them to execute stuff, which is not what we want, right? The only things that can be skipped compared to useCreateDao are the dao params and initial_items set up which are specific to regen marketplace in order to map the on chain created DAO to off chain organization in our db. Although maybe we should set up a consistent solution if the needs are similar? Again I think we are lacking proper specification here.

  3. Unless you index DAOs and RBAM assignments as we do in Regen Marketplace, the only way to query RBAM is through on chain queries, by querying list_assigments on the RBAM contract. This can be done through https://buf.build/cosmwasm/wasmd/docs/main%3Acosmwasm.wasm.v1#cosmwasm.wasm.v1.Query.SmartContractState

  4. We only have one active regen testnet: regen-upgrade

Comment thread api/ledger_anchor.py
return f"regen:{encoded}.rdf"


def generate_graph_iri(jsonld_doc: dict) -> str:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this seems to work as expected

Comment thread api/ledger_anchor.py
def build_attestation_jsonld(row) -> dict:
"""Build a JSON-LD document for an attestation record.

Uses inline @context to avoid remote URL fetches during canonicalization.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

that's totally fine
the below context is not yet available online afaik so inline context is the only viable solution for now anyway

Reviewer has a role in an org DAO (via RBAM) and signs `MsgAttest` on behalf of the org.

**Setup:**
1. Org creates a DAO via the Marketplace (useCreateDao pattern)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

do we really want to rely on the user having to go through the marketplace app first to set that up?
it doesn't look like a very optimized user flow

4. Reviewer's wallet gains permission to sign `MsgAttest` as a DAO member

**Signing:**
- Reviewer signs via `MsgExec` wrapping `MsgAttest`
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why MsgExec?? are you still talking about authz MsgExec, in which case it's off topic and unnecessary


5. **DAO DAO version compatibility** — Which version of DAO DAO is the Marketplace using? Are there breaking changes between versions we should pin against?

6. **Role assignment API** — Is there a REST/RPC endpoint to assign roles, or is it contract-execute only? For the pilot, we may want to script role assignment rather than going through the Marketplace UI.
Copy link
Copy Markdown

@blushi blushi Apr 15, 2026

Choose a reason for hiding this comment

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

contract execute only, for web3 users

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