⚙️  Backend Issue — Support Dynamic Sample Metadata Based on SampleType.json_schema_url
🎯  Goal
Enable SEPIA backend to handle dynamic metadata fields defined per SampleType via its associated json_schema_url.
This allows each sample type to define specific required and optional fields not included in the general database schema.
Dynamic metadata will be stored in the Sample.dynamic_sample_description field as JSON.
🧩  Implementation Details
1. Model Context
Existing model fields:
Sample.dynamic_sample_description (Optional[str])
SampleType.json_schema_url (Optional[str])
Each SampleType can define a JSON schema located at json_schema_url, describing additional metadata fields relevant to that type (e.g., chemical composition, preparation method, instrument settings, etc.).
2. Schema Handling
- 
On sample creation (
/sample), when a sample type is selected:- The backend retrieves or caches the JSON schema from 
json_schema_url. - Validate the provided 
dynamic_sample_descriptionJSON against that schema using a JSON Schema validator (e.g.,jsonschemalibrary). - If validation fails → return a structured 
400response with validation errors. 
 - The backend retrieves or caches the JSON schema from 
 - 
On sample read:
- Return the validated 
dynamic_sample_descriptionJSON in the API response as-is. 
 - Return the validated 
 - 
On sample update:
- Apply the same schema validation before saving.
 
 
3. Implementation Steps
- 
Schema Fetching
- Fetch JSON schema from 
SampleType.json_schema_url. - Cache in memory (or Redis? or other) to avoid repeated fetches.
 
 - Fetch JSON schema from 
 - 
Validation
- Use 
jsonschema.validate()to ensure input matches schema. - Include error details (path, expected type, etc.) in the response.
 
 - Use 
 - 
Storage
- Store the dynamic metadata JSON (as stringified JSON) in 
dynamic_sample_description. 
 - Store the dynamic metadata JSON (as stringified JSON) in 
 - 
Schema Updates
- If a schema changes, store only the latest version in cache and revalidate on next edit if required.
 
 
4. Example Flow
POST /sample
{
  "name": "Battery Sample A",
  "sample_type_id": 3,
  "dynamic_sample_description": {
    "cathode_material": "LiFePO4",
    "anode_material": "Graphite",
    "nominal_voltage": 3.7
  }
}
Schema (from SampleType.json_schema_url):
{
  "type": "object",
  "properties": {
    "cathode_material": {"type": "string"},
    "anode_material": {"type": "string"},
    "nominal_voltage": {"type": "number"}
  },
  "required": ["cathode_material", "anode_material"]
}
5. Error Example
{
  "error": "Invalid dynamic sample description",
  "details": [
    {"path": "/nominal_voltage", "message": "must be a number"},
    {"path": "/cathode_material", "message": "is required"}
  ]
}
🧪  Testing
- 
Validates dynamic fields per schema.  - 
Returns detailed validation errors.  - 
Schema fetched and cached correctly.  - 
Backward compatibility preserved for samples with no schema.  - 
Proper handling when schema URL is unreachable.  
🏷️  Labels
backend feature sample sample-type json-schema dynamic-metadata priority::high