Skip to content

Integrate regen-data-standards schemas: add @context, reference FWG taxonomy #11

@glandua

Description

@glandua

Summary

The claims engine should reference regen-data-standards (https://framework.regen.network/schema/) as its canonical schema vocabulary, rather than maintaining an independent ad-hoc schema. This is the single most important alignment issue for interop with the CLAMS CosmWasm contract (Spec B) and downstream consumers.

Context

The Framework Working Group (FWG) maintains LinkML schemas at regen-network/regen-data-standards that auto-generate JSON-LD contexts, JSON Schema, SHACL constraints, and RDF/TTL. The schemas use the rfs: (https://framework.regen.network/schema/) and rft: (https://framework.regen.network/taxonomy/) namespaces.

Claim and Attestation schemas have been proposed: regen-network/regen-data-standards#53 (PR open, replaces original issue #52).

Dependencies

Changes Required

  1. Add @context to canonical claim serialization
  2. Reference FWG taxonomy for claim type validation
  3. Add credit_class_id field
  4. Align proof pack output with FWG schema

Impact

  • Proof pack output becomes valid JSON-LD queryable by the FWG SPARQL endpoint
  • Spec B's JSON-LD deliverable (Sam) builds on existing FWG context rather than inventing a new one
  • Downstream consumers (PACTO, ASHA, Salmon Nation, RI Pod) get a governed vocabulary
  • Future DAO DAO schema governance applies to claim types automatically

Related

  • Spec B: Ethereum interop grant -- needs JSON-LD context as deliverable
  • ADR-004 in claims-engine coordination workspace

Implementation Spec (for Darren)

Note: This depends on regen-network/regen-data-standards#53 being merged. The spec can be implemented once the FWG schemas are published.

1. Add @context to _canonical_json()

In claims_router.py:_canonical_json(), prepend context fields:

def _canonical_json(claim_data: dict) -> str:
    """Build canonical JSON representation with FWG @context.
    
    The @context makes this valid JSON-LD without requiring full
    RDFC 1.0 canonicalization. The @type references the FWG Claim
    class from regen-data-standards.
    """
    canonical = {
        "@context": "https://framework.regen.network/schema/",
        "@type": "rfs:Claim",
        # ...existing fields in canonical order...
    }
    return json.dumps(canonical, sort_keys=True, separators=(',', ':'))

IMPORTANT: Adding @context changes the canonical form, which means new claims will produce different content hashes than old claims. This is a breaking change for RID generation — coordinate with #12 (hash unification) so both changes land together.

2. Same for _canonical_claim_json() in ledger_anchor.py

def _canonical_claim_json(claim_data: dict) -> str:
    """Build canonical JSON for on-chain anchoring with FWG @context."""
    canonical = {
        "@context": "https://framework.regen.network/schema/",
        "@type": "rfs:Claim",
        # ...existing anchor fields...
    }
    return json.dumps(canonical, sort_keys=True, separators=(',', ':'))

3. Validate claim_type against FWG taxonomy

Add a Pydantic validator to ClaimCreateRequest:

VALID_CLAIM_TYPES = {"ecological", "social", "financial", "governance", "biocultural"}

class ClaimCreateRequest(BaseModel):
    # ...existing fields...
    claim_type: str
    
    @validator('claim_type')
    def validate_claim_type(cls, v):
        normalized = v.lower().strip()
        if normalized not in VALID_CLAIM_TYPES:
            raise ValueError(
                f"Invalid claim_type '{v}'. "
                f"Must be one of: {', '.join(sorted(VALID_CLAIM_TYPES))}. "
                f"See regen-data-standards taxonomy.yaml ClaimType enum."
            )
        return normalized

This is hard validation — reject invalid types at the API boundary. The values map directly to the ClaimType enum in regen-data-standards/schema/src/taxonomy.yaml (ECOLOGICAL, SOCIAL, FINANCIAL, GOVERNANCE, BIOCULTURAL), normalized to lowercase for storage.

4. Add credit_class_id field

New Alembic migration:

"""Add credit_class_id to claims table"""

def upgrade():
    op.add_column('claims', sa.Column('credit_class_id', sa.Text(), nullable=True))
    op.create_index('ix_claims_credit_class_id', 'claims', ['credit_class_id'])

Add to ClaimCreateRequest:

class ClaimCreateRequest(BaseModel):
    # ...existing fields...
    credit_class_id: Optional[str] = None  # e.g., "C01", "C06", "BT01"

Include in canonical JSON when present:

if claim_data.get('credit_class_id'):
    canonical['hasCreditClass'] = claim_data['credit_class_id']

5. Add @context to proof pack response

Update the proof pack endpoint (GET /claims/{rid}/proof-pack) response model:

class ProofPackResponse(BaseModel):
    context: str = Field(
        alias="@context",
        default="https://framework.regen.network/schema/"
    )
    type: str = Field(alias="@type", default="rfs:Claim")
    # ...existing proof pack fields...
    
    class Config:
        populate_by_name = True

This makes the proof pack output valid JSON-LD. Sam can use this directly for Spec B's JSON-LD deliverable.

6. Breaking change coordination

Coordinate with #12 (hash unification):

Migration path:

  1. Land Unify content hash strategy: align RID and anchor hashing #12 first (BLAKE2b + 32 hex chars)
  2. Land Integrate regen-data-standards schemas: add @context, reference FWG taxonomy #11 immediately after (@context + validation)
  3. New claims get: BLAKE2b-256 RID + @context in canonical form
  4. Old claims: readable, queryable, but produce different canonical form if re-serialized

Acceptance Criteria

  • _canonical_json() includes @context and @type fields
  • _canonical_claim_json() in ledger_anchor.py includes @context and @type
  • claim_type validated against VALID_CLAIM_TYPES (rejects invalid types with helpful error)
  • New migration adds credit_class_id TEXT column with index
  • ClaimCreateRequest accepts optional credit_class_id
  • Proof pack response includes @context and @type (valid JSON-LD)
  • Existing 49+ dogfood claims still readable and queryable
  • Coordinated with Unify content hash strategy: align RID and anchor hashing #12 for hash change — both land in same release

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