Use Case Overview
Custom schemas enable specialized verification workflows that go beyond standard identity and ownership patterns. Create structured templates that enforce data integrity, enable complex business logic, and maintain interoperability across systems. Ideal For:- Industry-specific compliance requirements
- Proprietary credential systems
- Complex multi-step verification processes
- Regulatory reporting and audit trails
- Cross-platform interoperability standards
- Custom business process attestations
Schema Design Principles
Data Structure Planning
Design schemas with clear data hierarchy and validation rules:Copy
interface SchemaDesignPrinciples {
// 1. Field Types and Constraints
fieldTypes: {
// Primitive types for different data categories
identifiers: 'string' | 'address'; // IDs, addresses, references
quantities: 'uint8' | 'uint16' | 'uint32' | 'uint64'; // Numbers, amounts, counts
flags: 'bool'; // Boolean states
metadata: 'string' | 'bytes'; // Flexible data storage
timestamps: 'uint64'; // Time-based data
};
// 2. Naming Conventions
namingRules: {
descriptive: true; // Use clear, self-documenting field names
consistent: true; // Follow consistent naming patterns
versioned: true; // Include version information
namespaced: true; // Use prefixes for related fields
};
// 3. Data Minimization
dataStrategy: {
onChain: 'essential_only'; // Only critical data on-chain
offChain: 'detailed_records'; // Comprehensive data off-chain
hashed: 'sensitive_data'; // Hash sensitive information
};
// 4. Evolution Strategy
compatibility: {
backward: true; // Support older versions
forward: true; // Plan for future extensions
migration: true; // Define upgrade paths
};
}
Field Type Selection Guide
Choose appropriate field types for different data categories:Copy
// Identity and Reference Fields
const identityFields = {
userId: 'string', // User identifiers
walletAddress: 'address', // Blockchain addresses
sessionId: 'string', // Process references
externalId: 'string' // Third-party system IDs
};
// Quantitative Fields
const quantitativeFields = {
score: 'uint8', // Scores (0-255)
count: 'uint16', // Counts (0-65535)
amount: 'uint32', // Amounts (0-4B)
timestamp: 'uint64', // Unix timestamps
duration: 'uint32' // Time periods in seconds
};
// Categorical Fields
const categoricalFields = {
verified: 'bool', // Boolean states
status: 'string', // Enumerated states
level: 'string', // Tier/level indicators
type: 'string' // Category classifications
};
// Metadata Fields
const metadataFields = {
notes: 'string', // Text descriptions
tags: 'string', // Comma-separated tags
dataHash: 'bytes', // Content hashes
signature: 'bytes' // Cryptographic signatures
};
Custom Schema Implementation
Enterprise Compliance Schema
Design schemas for regulatory and compliance requirements:Copy
import { StellarAttestSDK, SolanaAttestSDK } from '@attestprotocol/sdk';
class ComplianceSchemaManager {
private sdk: StellarAttestSDK | SolanaAttestSDK;
private schemaRegistry: Map<string, SchemaDefinition> = new Map();
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async createComplianceSchemas(): Promise<Map<string, string>> {
const schemas = new Map<string, string>();
// Create all compliance schemas in parallel
const [amlSchema, soxSchema, gdprSchema] = await Promise.all([
this.createAMLSchema(),
this.createSOXSchema(),
this.createGDPRSchema()
]);
schemas.set('aml-screening', amlSchema);
schemas.set('sox-compliance', soxSchema);
schemas.set('gdpr-processing', gdprSchema);
return schemas;
}
async createIndustrySpecificSchemas(): Promise<Map<string, string>> {
const schemas = new Map<string, string>();
// Create industry schemas in parallel
const [hipaaSchema, finservSchema] = await Promise.all([
this.createHIPAASchema(),
this.createFinancialServicesSchema()
]);
schemas.set('hipaa-compliance', hipaaSchema);
schemas.set('finserv-authorization', finservSchema);
return schemas;
}
**AML Schema Creation**
```typescript
private async createAMLSchema(): Promise<string> {
// Anti-Money Laundering screening results schema
return await this.createSchema({
name: 'aml-screening-v1',
description: 'Anti-Money Laundering screening results',
definition: 'cleared:bool,riskLevel:uint8,checkDate:uint64,provider:string,sanctionsCheck:bool,pepCheck:bool,adverseMediaCheck:bool,nextReview:uint64,timestamp:uint64',
category: 'compliance',
revocable: true,
maxAge: 90 * 24 * 60 * 60, // 90 days
validationRules: {
riskLevel: { min: 0, max: 100 },
nextReview: { required: true },
provider: { allowed: ['chainalysis', 'elliptic', 'scorechain'] }
}
});
}
Copy
private async createSOXSchema(): Promise<string> {
// Sarbanes-Oxley compliance attestation schema
return await this.createSchema({
name: 'sox-compliance-v1',
description: 'Sarbanes-Oxley compliance attestation',
definition: 'compliant:bool,controlsTested:uint8,deficiencies:uint8,auditDate:uint64,auditor:string,certificationLevel:string,remediation:string,nextAudit:uint64,timestamp:uint64',
category: 'governance',
revocable: true,
maxAge: 365 * 24 * 60 * 60, // 1 year
validationRules: {
controlsTested: { min: 1 },
certificationLevel: { allowed: ['basic', 'enhanced', 'comprehensive'] },
auditor: { required: true }
}
});
}
Copy
private async createGDPRSchema(): Promise<string> {
// GDPR data processing compliance schema
return await this.createSchema({
name: 'gdpr-data-processing-v1',
description: 'GDPR data processing compliance',
definition: 'lawfulBasis:string,dataCategories:string,processingPurpose:string,retentionPeriod:uint32,consentObtained:bool,dataMinimized:bool,securityMeasures:string,dpoApproved:bool,timestamp:uint64',
category: 'privacy',
revocable: true,
maxAge: 180 * 24 * 60 * 60, // 6 months
validationRules: {
lawfulBasis: { allowed: ['consent', 'contract', 'legal_obligation', 'vital_interests', 'public_task', 'legitimate_interests'] },
retentionPeriod: { max: 7 * 365 * 24 * 60 * 60 }, // Max 7 years
consentObtained: { required: true },
dpoApproved: { required: true }
}
});
}
Copy
private async createHIPAASchema(): Promise<string> {
// Healthcare HIPAA compliance verification schema
return await this.createSchema({
name: 'hipaa-compliance-v1',
description: 'Healthcare HIPAA compliance verification',
definition: 'covered:bool,associateType:string,trainingComplete:bool,trainingDate:uint64,accessLevel:string,auditTrail:bool,encryptionUsed:bool,incidentCount:uint8,lastReview:uint64,timestamp:uint64',
category: 'healthcare',
revocable: true,
maxAge: 365 * 24 * 60 * 60,
validationRules: {
associateType: { allowed: ['covered_entity', 'business_associate', 'subcontractor'] },
accessLevel: { allowed: ['basic', 'administrative', 'clinical', 'technical'] },
trainingComplete: { required: true }
}
});
}
Copy
private async createFinancialServicesSchema(): Promise<string> {
// Financial services authorization and licensing schema
return await this.createSchema({
name: 'finserv-authorization-v1',
description: 'Financial services authorization and licensing',
definition: 'licensed:bool,licenseType:string,licenseNumber:string,jurisdiction:string,issuedDate:uint64,expiryDate:uint64,supervisoryBody:string,capitalRequirement:uint64,bondRequired:bool,bondAmount:uint64,timestamp:uint64',
category: 'financial',
revocable: true,
maxAge: 30 * 24 * 60 * 60, // 30 days
validationRules: {
licenseType: { allowed: ['broker_dealer', 'investment_advisor', 'money_transmitter', 'bank', 'credit_union'] },
capitalRequirement: { min: 0 },
bondRequired: { required: true }
}
});
}
private async createSchema(definition: SchemaDefinition): Promise<string> {
// Validate schema definition
this.validateSchemaDefinition(definition);
// Create schema on-chain
const result = await this.sdk.createSchema({
schemaName: definition.name,
schemaContent: definition.definition,
revocable: definition.revocable
});
if (result.error) {
throw new Error(`Schema creation failed: ${result.error}`);
}
// Store schema metadata
this.schemaRegistry.set(definition.name, {
...definition,
schemaUID: result.data.schemaUID,
createdAt: Date.now()
});
return result.data.schemaUID;
}
private validateSchemaDefinition(definition: SchemaDefinition): void {
// Validate field definitions
const fields = definition.definition.split(',');
const fieldNames = new Set<string>();
for (const field of fields) {
const [name, type] = field.split(':');
if (!name || !type) {
throw new Error(`Invalid field definition: ${field}`);
}
if (fieldNames.has(name)) {
throw new Error(`Duplicate field name: ${name}`);
}
fieldNames.add(name);
if (!this.isValidFieldType(type)) {
throw new Error(`Invalid field type: ${type}`);
}
}
// Validate required fields
const requiredFields = ['timestamp'];
for (const required of requiredFields) {
if (!fieldNames.has(required)) {
throw new Error(`Missing required field: ${required}`);
}
}
// Validate naming conventions
if (!definition.name.includes('-v')) {
throw new Error('Schema name must include version identifier');
}
}
private isValidFieldType(type: string): boolean {
const validTypes = [
'bool', 'string', 'uint8', 'uint16', 'uint32', 'uint64',
'int8', 'int16', 'int32', 'int64', 'address', 'bytes'
];
return validTypes.includes(type);
}
}
interface SchemaDefinition {
name: string;
description: string;
definition: string;
category: string;
revocable: boolean;
maxAge?: number;
validationRules?: Record<string, any>;
schemaUID?: string;
createdAt?: number;
}
Multi-Step Process Schema
Design schemas for complex, multi-step verification processes:Copy
class ProcessSchemaManager {
private sdk: StellarAttestSDK | SolanaAttestSDK;
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async createProcessSchemas(): Promise<Map<string, string>> {
const schemas = new Map<string, string>();
// Loan Approval Process Schema
const loanProcessSchema = await this.createProcessSchema({
name: 'loan-approval-process-v1',
description: 'Multi-step loan approval process tracking',
steps: [
{
name: 'application_submitted',
fields: 'applicationId:string,applicant:address,requestedAmount:uint64,purpose:string,submittedDate:uint64'
},
{
name: 'credit_check_completed',
fields: 'applicationId:string,creditScore:uint16,creditProvider:string,checkDate:uint64,approved:bool'
},
{
name: 'income_verification',
fields: 'applicationId:string,incomeVerified:bool,employmentStatus:string,verificationMethod:string,verifiedDate:uint64'
},
{
name: 'collateral_assessment',
fields: 'applicationId:string,collateralType:string,assessedValue:uint64,assessor:string,assessmentDate:uint64'
},
{
name: 'final_approval',
fields: 'applicationId:string,approved:bool,approvedAmount:uint64,interestRate:uint16,termMonths:uint16,approver:string,approvalDate:uint64'
}
],
category: 'lending',
revocable: false
});
schemas.set('loan-process', loanProcessSchema);
// Clinical Trial Participation Schema
const clinicalTrialSchema = await this.createProcessSchema({
name: 'clinical-trial-participation-v1',
description: 'Clinical trial participant tracking',
steps: [
{
name: 'screening',
fields: 'trialId:string,participant:address,eligibilityMet:bool,consentSigned:bool,screeningDate:uint64'
},
{
name: 'enrollment',
fields: 'trialId:string,participant:address,enrolled:bool,cohort:string,enrollmentDate:uint64,randomizationCode:string'
},
{
name: 'treatment_administration',
fields: 'trialId:string,participant:address,treatmentGroup:string,dosage:string,administrationDate:uint64,sideEffects:string'
},
{
name: 'follow_up',
fields: 'trialId:string,participant:address,followUpDate:uint64,responseAssessment:string,adverseEvents:string,continueTreatment:bool'
},
{
name: 'completion',
fields: 'trialId:string,participant:address,completed:bool,completionDate:uint64,reason:string,finalAssessment:string'
}
],
category: 'healthcare',
revocable: false
});
schemas.set('clinical-trial', clinicalTrialSchema);
return schemas;
}
private async createProcessSchema(definition: ProcessSchemaDefinition): Promise<string> {
// Create individual schemas for each step
const stepSchemas: string[] = [];
for (const step of definition.steps) {
const stepSchemaName = `${definition.name}-${step.name}`;
const stepDefinition = `${step.fields},stepNumber:uint8,processId:string,timestamp:uint64`;
const result = await this.sdk.createSchema({
schemaName: stepSchemaName,
schemaContent: stepDefinition,
revocable: definition.revocable
});
if (result.error) {
throw new Error(`Step schema creation failed: ${result.error}`);
}
stepSchemas.push(result.data.schemaUID);
}
// Create master process schema
const masterDefinition = `processType:string,totalSteps:uint8,currentStep:uint8,status:string,startedDate:uint64,completedDate:uint64,timestamp:uint64`;
const masterResult = await this.sdk.createSchema({
schemaName: definition.name,
schemaContent: masterDefinition,
revocable: definition.revocable
});
if (masterResult.error) {
throw new Error(`Master process schema creation failed: ${masterResult.error}`);
}
return masterResult.data.schemaUID;
}
}
interface ProcessStep {
name: string;
fields: string;
}
interface ProcessSchemaDefinition {
name: string;
description: string;
steps: ProcessStep[];
category: string;
revocable: boolean;
}
Advanced Schema Patterns
Hierarchical Schema System
Create schemas that build upon each other:Copy
class HierarchicalSchemaManager {
private sdk: StellarAttestSDK | SolanaAttestSDK;
private schemaHierarchy: Map<string, string[]> = new Map();
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async createEducationHierarchy(): Promise<Map<string, string>> {
const schemas = new Map<string, string>();
// Base education schema
const baseEducationSchema = await this.sdk.createSchema({
schemaName: 'education-base-v1',
schemaContent: 'hasEducation:bool,level:string,verified:bool,timestamp:uint64',
revocable: false
});
if (baseEducationSchema.error) {
throw new Error(`Base education schema failed: ${baseEducationSchema.error}`);
}
schemas.set('education-base', baseEducationSchema.data.schemaUID);
// High school diploma schema (extends base)
const highSchoolSchema = await this.sdk.createSchema({
schemaName: 'education-highschool-v1',
schemaContent: 'hasEducation:bool,level:string,verified:bool,institution:string,graduationYear:uint16,gpa:uint8,honors:string,transcript:string,timestamp:uint64',
revocable: false
});
if (highSchoolSchema.error) {
throw new Error(`High school schema failed: ${highSchoolSchema.error}`);
}
schemas.set('education-highschool', highSchoolSchema.data.schemaUID);
// Bachelor's degree schema (extends high school)
const bachelorSchema = await this.sdk.createSchema({
schemaName: 'education-bachelor-v1',
schemaContent: 'hasEducation:bool,level:string,verified:bool,institution:string,graduationYear:uint16,gpa:uint8,honors:string,transcript:string,major:string,minor:string,credits:uint16,accreditation:string,timestamp:uint64',
revocable: false
});
if (bachelorSchema.error) {
throw new Error(`Bachelor schema failed: ${bachelorSchema.error}`);
}
schemas.set('education-bachelor', bachelorSchema.data.schemaUID);
// Graduate degree schema (extends bachelor)
const graduateSchema = await this.sdk.createSchema({
schemaName: 'education-graduate-v1',
schemaContent: 'hasEducation:bool,level:string,verified:bool,institution:string,graduationYear:uint16,gpa:uint8,honors:string,transcript:string,major:string,minor:string,credits:uint16,accreditation:string,degreeType:string,thesis:string,advisor:string,researchArea:string,timestamp:uint64',
revocable: false
});
if (graduateSchema.error) {
throw new Error(`Graduate schema failed: ${graduateSchema.error}`);
}
schemas.set('education-graduate', graduateSchema.data.schemaUID);
// Define hierarchy relationships
this.schemaHierarchy.set('education-base', []);
this.schemaHierarchy.set('education-highschool', ['education-base']);
this.schemaHierarchy.set('education-bachelor', ['education-highschool']);
this.schemaHierarchy.set('education-graduate', ['education-bachelor']);
return schemas;
}
async verifyHierarchicalRequirements(
userAddress: string,
targetSchema: string
): Promise<HierarchyVerificationResult> {
const requiredSchemas = this.schemaHierarchy.get(targetSchema) || [];
const verificationResults: Map<string, boolean> = new Map();
for (const requiredSchema of requiredSchemas) {
const attestation = await this.sdk.fetchAttestation({
schemaUID: requiredSchema,
subject: userAddress
});
verificationResults.set(
requiredSchema,
!!(attestation.data && !attestation.data.revoked)
);
}
const allRequirementsMet = Array.from(verificationResults.values()).every(met => met);
return {
eligible: allRequirementsMet,
requiredSchemas,
verificationResults,
missingRequirements: Array.from(verificationResults.entries())
.filter(([, met]) => !met)
.map(([schema]) => schema)
};
}
}
interface HierarchyVerificationResult {
eligible: boolean;
requiredSchemas: string[];
verificationResults: Map<string, boolean>;
missingRequirements: string[];
}
Composite Schema Pattern
Combine multiple verification types into unified schemas:Copy
class CompositeSchemaManager {
private sdk: StellarAttestSDK | SolanaAttestSDK;
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async createEmploymentVerificationComposite(): Promise<string> {
// Comprehensive employment verification combining multiple checks
const compositeSchema = await this.sdk.createSchema({
schemaName: 'employment-verification-composite-v1',
schemaContent: 'employed:bool,employer:string,position:string,startDate:uint64,salary:uint64,verified:bool,backgroundCheck:bool,referenceCheck:bool,skillAssessment:bool,educationVerified:bool,identityVerified:bool,creditCheck:bool,drugTest:bool,verificationScore:uint8,timestamp:uint64',
revocable: true
});
if (compositeSchema.error) {
throw new Error(`Composite schema creation failed: ${compositeSchema.error}`);
}
return compositeSchema.data.schemaUID;
}
async issueCompositeAttestation(
subjectAddress: string,
verificationData: EmploymentVerificationData
): Promise<string> {
// Calculate composite verification score
const score = this.calculateCompositeScore(verificationData);
// Create composite attestation value
const attestationValue = `employed:${verificationData.employed},employer:${verificationData.employer},position:${verificationData.position},startDate:${verificationData.startDate},salary:${verificationData.salary},verified:${verificationData.verified},backgroundCheck:${verificationData.backgroundCheck},referenceCheck:${verificationData.referenceCheck},skillAssessment:${verificationData.skillAssessment},educationVerified:${verificationData.educationVerified},identityVerified:${verificationData.identityVerified},creditCheck:${verificationData.creditCheck},drugTest:${verificationData.drugTest},verificationScore:${score},timestamp:${Math.floor(Date.now() / 1000)}`;
const attestation = await this.sdk.attest({
schemaUID: 'employment-verification-composite-v1',
subject: subjectAddress,
value: attestationValue,
reference: `employment-composite-${Date.now()}`
});
if (attestation.error) {
throw new Error(`Composite attestation failed: ${attestation.error}`);
}
return attestation.data;
}
private calculateCompositeScore(data: EmploymentVerificationData): number {
let score = 0;
let maxScore = 0;
// Weight different verification types
const weights = {
employed: 20,
verified: 15,
backgroundCheck: 10,
referenceCheck: 10,
skillAssessment: 10,
educationVerified: 10,
identityVerified: 15,
creditCheck: 5,
drugTest: 5
};
Object.entries(weights).forEach(([key, weight]) => {
maxScore += weight;
if (data[key as keyof EmploymentVerificationData]) {
score += weight;
}
});
return Math.round((score / maxScore) * 100);
}
}
interface EmploymentVerificationData {
employed: boolean;
employer: string;
position: string;
startDate: number;
salary: number;
verified: boolean;
backgroundCheck: boolean;
referenceCheck: boolean;
skillAssessment: boolean;
educationVerified: boolean;
identityVerified: boolean;
creditCheck: boolean;
drugTest: boolean;
}
Schema Testing and Validation
Comprehensive Testing Framework
Implement thorough schema testing:Copy
class SchemaTestFramework {
private sdk: StellarAttestSDK | SolanaAttestSDK;
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async testSchemaDefinition(
schemaDefinition: string,
testCases: SchemaTestCase[]
): Promise<SchemaTestResult> {
const results: TestCaseResult[] = [];
for (const testCase of testCases) {
try {
const result = await this.validateSchemaData(schemaDefinition, testCase.data);
results.push({
name: testCase.name,
data: testCase.data,
expected: testCase.expected,
actual: result.valid,
passed: result.valid === testCase.expected,
errors: result.errors
});
} catch (error) {
results.push({
name: testCase.name,
data: testCase.data,
expected: testCase.expected,
actual: false,
passed: false,
errors: [error.message]
});
}
}
const passed = results.filter(r => r.passed).length;
const total = results.length;
return {
schemaDefinition,
testCases: results,
summary: {
total,
passed,
failed: total - passed,
successRate: (passed / total) * 100
}
};
}
private async validateSchemaData(
schemaDefinition: string,
data: string
): Promise<{ valid: boolean; errors: string[] }> {
const errors: string[] = [];
// Parse schema definition
const schemaFields = this.parseSchemaDefinition(schemaDefinition);
const dataFields = this.parseDataString(data);
// Check required fields
for (const field of schemaFields) {
if (!dataFields.has(field.name)) {
errors.push(`Missing required field: ${field.name}`);
} else {
// Validate field type
const value = dataFields.get(field.name)!;
if (!this.validateFieldType(value, field.type)) {
errors.push(`Invalid type for field ${field.name}: expected ${field.type}, got ${typeof value}`);
}
}
}
// Check for extra fields
for (const [fieldName] of dataFields) {
if (!schemaFields.find(f => f.name === fieldName)) {
errors.push(`Unexpected field: ${fieldName}`);
}
}
return {
valid: errors.length === 0,
errors
};
}
private parseSchemaDefinition(definition: string): SchemaField[] {
return definition.split(',').map(field => {
const [name, type] = field.split(':');
return { name: name.trim(), type: type.trim() };
});
}
private parseDataString(data: string): Map<string, string> {
const fields = new Map<string, string>();
data.split(',').forEach(pair => {
const [key, value] = pair.split(':');
fields.set(key.trim(), value.trim());
});
return fields;
}
private validateFieldType(value: string, expectedType: string): boolean {
switch (expectedType) {
case 'bool':
return value === 'true' || value === 'false';
case 'uint8':
const uint8Value = parseInt(value);
return !isNaN(uint8Value) && uint8Value >= 0 && uint8Value <= 255;
case 'uint16':
const uint16Value = parseInt(value);
return !isNaN(uint16Value) && uint16Value >= 0 && uint16Value <= 65535;
case 'uint32':
const uint32Value = parseInt(value);
return !isNaN(uint32Value) && uint32Value >= 0 && uint32Value <= 4294967295;
case 'uint64':
const uint64Value = parseInt(value);
return !isNaN(uint64Value) && uint64Value >= 0;
case 'string':
return typeof value === 'string' && value.length > 0;
case 'address':
return /^[a-zA-Z0-9]{20,64}$/.test(value); // Simplified address validation
case 'bytes':
return /^0x[a-fA-F0-9]*$/.test(value); // Hex string validation
default:
return false;
}
}
}
interface SchemaField {
name: string;
type: string;
}
interface SchemaTestCase {
name: string;
data: string;
expected: boolean; // Should this data be valid?
}
interface TestCaseResult {
name: string;
data: string;
expected: boolean;
actual: boolean;
passed: boolean;
errors: string[];
}
interface SchemaTestResult {
schemaDefinition: string;
testCases: TestCaseResult[];
summary: {
total: number;
passed: number;
failed: number;
successRate: number;
};
}
Best Practices
Schema Evolution Strategy
Plan for schema updates and migrations:Copy
class SchemaEvolutionManager {
private sdk: StellarAttestSDK | SolanaAttestSDK;
private versionRegistry: Map<string, SchemaVersion[]> = new Map();
constructor(sdk: StellarAttestSDK | SolanaAttestSDK) {
this.sdk = sdk;
}
async planSchemaEvolution(
currentSchemaUID: string,
proposedDefinition: string
): Promise<EvolutionPlan> {
const currentSchema = await this.getSchemaDefinition(currentSchemaUID);
if (!currentSchema) {
throw new Error('Current schema not found');
}
const compatibility = this.analyzeCompatibility(
currentSchema.definition,
proposedDefinition
);
return {
currentVersion: currentSchema.version,
proposedVersion: this.incrementVersion(currentSchema.version),
compatibility,
migrationRequired: !compatibility.backwardCompatible,
migrationStrategy: this.generateMigrationStrategy(compatibility),
risks: this.assessMigrationRisks(compatibility)
};
}
private analyzeCompatibility(
currentDefinition: string,
proposedDefinition: string
): CompatibilityAnalysis {
const currentFields = this.parseSchemaDefinition(currentDefinition);
const proposedFields = this.parseSchemaDefinition(proposedDefinition);
const removedFields = currentFields.filter(
current => !proposedFields.find(proposed => proposed.name === current.name)
);
const addedFields = proposedFields.filter(
proposed => !currentFields.find(current => current.name === proposed.name)
);
const modifiedFields = currentFields.filter(current => {
const proposed = proposedFields.find(p => p.name === current.name);
return proposed && proposed.type !== current.type;
});
return {
backwardCompatible: removedFields.length === 0 && modifiedFields.length === 0,
forwardCompatible: addedFields.length === 0 && modifiedFields.length === 0,
removedFields,
addedFields,
modifiedFields
};
}
private generateMigrationStrategy(
compatibility: CompatibilityAnalysis
): MigrationStrategy {
if (compatibility.backwardCompatible) {
return {
type: 'seamless',
steps: [
'Deploy new schema version',
'Update applications to use new schema',
'Existing attestations remain valid'
]
};
}
if (compatibility.removedFields.length > 0 || compatibility.modifiedFields.length > 0) {
return {
type: 'breaking',
steps: [
'Create migration mapping for existing attestations',
'Deploy new schema version',
'Migrate existing attestations to new format',
'Update applications to use new schema',
'Deprecate old schema version'
]
};
}
return {
type: 'additive',
steps: [
'Deploy new schema version with optional fields',
'Update applications incrementally',
'Backfill new fields where possible'
]
};
}
private assessMigrationRisks(compatibility: CompatibilityAnalysis): string[] {
const risks: string[] = [];
if (compatibility.removedFields.length > 0) {
risks.push('Data loss: Removed fields will lose information');
risks.push('Application compatibility: Existing applications may break');
}
if (compatibility.modifiedFields.length > 0) {
risks.push('Type conversion: Field type changes may cause data corruption');
risks.push('Validation failures: Existing data may not pass new validation');
}
if (!compatibility.backwardCompatible) {
risks.push('Breaking change: Requires coordinated deployment');
risks.push('Downtime: May require service interruption');
}
return risks;
}
}
interface SchemaVersion {
version: string;
schemaUID: string;
definition: string;
createdAt: number;
deprecated?: boolean;
}
interface CompatibilityAnalysis {
backwardCompatible: boolean;
forwardCompatible: boolean;
removedFields: SchemaField[];
addedFields: SchemaField[];
modifiedFields: SchemaField[];
}
interface MigrationStrategy {
type: 'seamless' | 'additive' | 'breaking';
steps: string[];
}
interface EvolutionPlan {
currentVersion: string;
proposedVersion: string;
compatibility: CompatibilityAnalysis;
migrationRequired: boolean;
migrationStrategy: MigrationStrategy;
risks: string[];
}