Skip to content

SPIKE: Plugin transformation contract and SDK integration strategy #657

@SnowboardTechie

Description

@SnowboardTechie

Summary

Research the minimal plugin transformation contract, its TypeScript and Python API shape, and how protocol-defined mappings and runtime utilities should integrate with that contract.

Context

ADR 0017 defines a JSON mapping format for declarative transformations. Runtime implementations already exist:

  • Python SDK: transform_from_mapping() with field and switch handlers
  • Website: transformWithMapping() with the same handler set

However, these utilities exist in isolation — there's no formal plugin contract that defines what a transformation interface should look like. The PA and CA example APIs use imperative class-based transformers (OpportunityTransformer) that don't use the mapping utilities at all.

This spike should define the transform contract first, then determine how mapping utilities fit behind that contract.

Design constraints

The repo's public API style leans structural and simple:

  • TypeScript plugin system uses structural typing
  • Python uses simple dataclasses and config objects
  • Avoid inheritance-heavy abstract base class hierarchies

The transform contract should feel like a small interface or plain object contract, not an elaborate class hierarchy.

Questions to answer

  1. Minimal contract shape: What is the minimal transform interface? A single function signature? A config object with transform methods?

  2. Directionality: Should the contract be directional?

    • transformToCommonGrants(source: S) -> T (required)
    • transformFromCommonGrants(cg: T) -> S (optional, for round-trip scenarios)
  3. Structural vs class-based: Should the contract be:

    • A structural interface (TS) / Protocol (Python) that any conforming object satisfies?
    • A factory function pattern?
    • A class-based approach (like the existing OpportunityTransformer in examples)?
  4. Mapping integration: How does the JSON mapping format fit into the contract?

    • Required (all plugins must use mappings)?
    • Optional utility (one way to implement the contract)?
    • Separate concern (mapping runtime is independent of adapter contract)?
  5. Porting the website utility: Can website/src/lib/transformation.ts be ported directly to @common-grants/sdk, or should it be adapted to fit behind the contract interface?

  6. Validation boundaries: What should the SDK validate, and at what layer?

    • plugin transform output validation: How should the SDK verify that transformed output conforms to CommonGrants models?
    • Compile-time type checking only?
    • Runtime schema validation?
    • Both?
  • Mapping definition validation: If mapping utilities are exposed, how should the SDK validate mapping definitions?
    • Validate only against the ADR 0017 / MappingSchema structure?
    • Also validate compatibility with the runtime's supported handler set?
    • When should validation happen: authoring time, load time, or execution time?
  1. Handler extensibility: If mapping utilities are exposed, how do users register custom handlers? What's the DX for adding a myCustomHandler transformation?

  2. Error handling: What context should transformation errors include? (path, handler name, input value, expected type?)

Acceptance criteria

  • Technical recommendation document addressing the questions above
  • Proposed transform contract shape for TypeScript with code examples
  • Proposed transform contract shape for Python with code examples
  • Recommendation on how mapping utilities integrate with the contract
  • Assessment of whether website transformWithMapping() can be ported directly
  • Recommended validation strategy (compile-time, runtime, or both)
  • Refined set of implementation sub-issues created under epic [SDK] Define and support a standard plugin transformation interface #656, grouped by:
    • contract / API definition
    • SDK validation behavior
    • optional mapping runtime utility work
    • examples / documentation updates

Related

Metadata

Metadata

Labels

sdkIssue or PR related to our SDKs

Type

No fields configured for Task.

Projects

Status

In Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions