SDK Guide
Validator

License Validator

The validator ensures license configurations comply with the NIL Taxonomy specification.

Basic Usage

import { validateLicense } from '@nil-taxonomy/sdk';
 
const result = validateLicense({
  subject_scope: ['name', 'image'],
  use_type: ['brand_marketing'],
  commercial_scope: 'full_commercial',
  // ... other fields
});
 
if (!result.valid) {
  console.error('Validation failed:', result.errors);
}

Validation Result

interface ValidationResult {
  valid: boolean;
  errors?: ValidationError[];
  warnings?: ValidationWarning[];
}
 
interface ValidationError {
  field: string;
  message: string;
  code: string;
  value?: any;
}
 
interface ValidationWarning {
  field: string;
  message: string;
  code: string;
  severity: 'low' | 'medium' | 'high';
}

Validation Rules

Required Fields

All licenses must include:

{
  subject_scope: SubjectScope[],      // REQUIRED
  use_type: UseType[],                // REQUIRED
  commercial_scope: CommercialScope,  // REQUIRED
  exclusivity: Exclusivity,           // REQUIRED
  territory: Territory,               // REQUIRED
  term: Term,                         // REQUIRED (or perpetual)
  derivative_rights: DerivativeRights,// REQUIRED
  ai_synthetic_use: AISyntheticUse,   // REQUIRED
  data_use: DataUse,                  // REQUIRED
  attribution: Attribution,           // REQUIRED
  sublicensing: Sublicensing,         // REQUIRED
  content_safety: ContentSafety       // REQUIRED
}

Field-Specific Validation

Subject Scope:

  • Must be non-empty array
  • Must contain only valid enum values
  • synthetic_likeness requires ai_synthetic_use to allow it

Use Type:

  • Must be non-empty array
  • brand_marketing requires commercial_scope = full_commercial
  • educational requires commercial_scope = non_commercial

Territory:

  • Must specify at least one of: global, countries, regions, states, cities
  • Country codes must be ISO 3166-1 alpha-2
  • Cannot mix global: true with specific territories

Term:

  • Start date must be before end date
  • If auto-renew, must specify renewal period
  • Perpetual and fixed-term are mutually exclusive

Exclusivity:

  • If category_exclusive, must specify categories
  • If full_exclusive, cannot specify categories
  • Exclusive categories must be valid enum values

Content Safety:

  • Restricted categories must be valid enum values
  • If morals clause = 'custom', must provide text
  • Competitor exclusions must be non-empty if provided

Error Codes

Common validation error codes:

CodeDescriptionExample Fix
REQUIRED_FIELDMissing required fieldAdd the field
INVALID_ENUMInvalid enum valueUse valid taxonomy value
INVALID_FORMATIncorrect data formatCheck type (string vs array)
LOGICAL_CONFLICTConflicting valuesAdjust incompatible settings
MISSING_DEPENDENCYDependent field missingAdd required related field

Warnings

Warnings indicate potential issues but don't prevent building:

const result = validateLicense(license);
 
if (result.valid && result.warnings?.length) {
  result.warnings.forEach(warning => {
    console.warn(`${warning.severity.toUpperCase()}: ${warning.message}`);
  });
}

Warning Types

High Severity:

  • Unrestricted AI use without approval process
  • Full exclusive without specified term
  • Marketing data use without opt-in

Medium Severity:

  • Global territory with short term
  • UGC rights without content safety guardrails
  • Perpetual term with auto-renewal

Low Severity:

  • Missing attribution for commercial use
  • No competitor exclusions for exclusive deals
  • Sublicensing allowed without restrictions

Validation Examples

Valid License

const license = {
  subject_scope: ['name', 'image'],
  use_type: ['brand_marketing'],
  commercial_scope: 'full_commercial',
  exclusivity: 'none',
  territory: { countries: ['US'] },
  term: {
    start_date: '2024-01-01',
    end_date: '2025-12-31',
    auto_renew: false
  },
  derivative_rights: 'limited',
  ai_synthetic_use: 'prohibited',
  data_use: { level: 'aggregated_anon' },
  attribution: 'name_required',
  sublicensing: 'prohibited',
  content_safety: {
    restricted_categories: ['adult', 'tobacco']
  }
};
 
const result = validateLicense(license);
// result.valid = true

Invalid License (Missing Required Field)

const invalidLicense = {
  subject_scope: ['name', 'image'],
  // Missing required fields
};
 
const result = validateLicense(invalidLicense);
// result.valid = false
// result.errors = [
//   { field: 'use_type', message: 'Required field missing', code: 'REQUIRED_FIELD' },
//   { field: 'commercial_scope', ... },
//   ...
// ]

Invalid Enum Value

const license = {
  subject_scope: ['name', 'invalid_value'], // ❌ Invalid
  // ...
};
 
const result = validateLicense(license);
// result.valid = false
// result.errors = [
//   {
//     field: 'subject_scope',
//     message: 'Invalid value: invalid_value',
//     code: 'INVALID_ENUM',
//     value: 'invalid_value'
//   }
// ]

Logical Conflict

const license = {
  use_type: ['educational'], // ❌ Conflicts with commercial_scope
  commercial_scope: 'full_commercial',
  // ...
};
 
const result = validateLicense(license);
// result.valid = false
// result.errors = [
//   {
//     field: 'commercial_scope',
//     message: 'Educational use requires non_commercial scope',
//     code: 'LOGICAL_CONFLICT'
//   }
// ]

Safe Building with tryBuild()

The builder's tryBuild() method returns a result object instead of throwing:

const result = new NILLicenseBuilder()
  .setSubjectScope(['name'])
  .tryBuild();
 
if (!result.success) {
  console.error('Validation errors:');
  result.errors.forEach(err => {
    console.error(`- ${err.field}: ${err.message}`);
  });
  process.exit(1);
}
 
const license = result.license;

Best Practices

1. Always Validate

// ✅ Good: Validate before using
const license = builder.build();
const validation = validateLicense(license);
if (!validation.valid) {
  throw new Error('Invalid license');
}
 
// ❌ Risky: Skip validation
const license = builder.build();
await saveToDB(license); // Might save invalid data

2. Handle Warnings

const result = validateLicense(license);
 
if (result.valid) {
  const highRiskWarnings = result.warnings?.filter(
    w => w.severity === 'high'
  );
  
  if (highRiskWarnings?.length) {
    // Require additional review for high-risk configs
    await requestManagerApproval(license);
  }
}

3. Provide User Feedback

const result = validateLicense(userSubmittedLicense);
 
if (!result.valid) {
  return {
    success: false,
    errors: result.errors.map(e => ({
      field: e.field,
      message: e.message
    }))
  };
}

Validation in Forms

Example React form validation:

function LicenseForm() {
  const [errors, setErrors] = useState<ValidationError[]>([]);
  
  const handleSubmit = () => {
    const license = buildLicenseFromForm();
    const result = validateLicense(license);
    
    if (!result.valid) {
      setErrors(result.errors || []);
      return;
    }
    
    // Proceed with valid license
    saveLicense(license);
  };
  
  return (
    <form>
      {/* Form fields */}
      {errors.length > 0 && (
        <div className="errors">
          {errors.map(err => (
            <p key={err.field}>{err.field}: {err.message}</p>
          ))}
        </div>
      )}
    </form>
  );
}

Next Steps