Source code for rsm_schema.generated.models

# generated by datamodel-codegen:
#   filename:  rsm.schema.json

from enum import StrEnum
from typing import Annotated

from pydantic import BaseModel, ConfigDict, EmailStr, Field, RootModel


class DevelopmentStatus(StrEnum):
    """Current repostatus.org lifecycle status for the software."""

    concept = "concept"
    wip = "wip"
    active = "active"
    inactive = "inactive"
    suspended = "suspended"
    abandoned = "abandoned"
    unsupported = "unsupported"
    moved = "moved"


class Entry(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class Keywords(BaseModel):
    """Public keywords used in package metadata, citation metadata, registries, and archives."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry]


class Entry1(StrEnum):
    data_collection___instrumentation = "Data collection & instrumentation"
    data_analysis = "Data analysis"
    simulation = "Simulation"
    visualization___dissemination = "Visualization & dissemination"
    software_reuse = "Software reuse"
    integration___interfacing = "Integration & interfacing"


class Categories(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry1]


class Motivation(BaseModel):
    """Public purpose, purpose categories, problem statement, and value proposition."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    purpose: str | None = None
    categories: Categories | None = None
    problem_statement: str | None = None
    value_proposition: str | None = None


class Entry2(StrEnum):
    researchers__academia_ = "Researchers (academia)"
    clinicians___healthcare_professionals = "Clinicians / healthcare professionals"
    data_stewards___data_managers = "Data stewards / data managers"
    bioinformaticians___computational_scientists = "Bioinformaticians / computational scientists"
    lab_scientists = "Lab scientists"
    students___educators = "Students / educators"
    software_developers___rs_es = "Software developers / RSEs"
    institutional_it_staff___system_administrators = (
        "Institutional IT staff / system administrators"
    )
    policy_makers___funders = "Policy makers / funders"
    industry_users___pharma___biotech = "Industry users / pharma / biotech"
    general_public___citizen_scientists = "General public / citizen scientists"


class Audiences(BaseModel):
    """Intended users or stakeholder groups."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry2]


class Urls(BaseModel):
    """Canonical source repository, project homepage, and published documentation URLs."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    repository: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
    homepage: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
    documentation: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None


class CompatibilityCheck(StrEnum):
    yes___automated_tooling = "Yes - automated tooling"
    yes___manual_check = "Yes - manual check"


class Licensing(BaseModel):
    """License text or SPDX identifier and the selected dependency-license compatibility method."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    license: str | None = None
    compatibility_check: CompatibilityCheck | None = None


class Type(StrEnum):
    """Whether access to the software is free, free with restrictions, or commercial."""

    free = "free"
    free_with_restrictions = "free-with-restrictions"
    commercial = "commercial"


class Access(BaseModel):
    """How users can obtain or use the software, independently of its copyright license."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    type: Type | None = None
    """Whether access to the software is free, free with restrictions, or commercial."""
    details: str | None = None
    """Public explanation or URL describing eligibility, quotas, institutional or non-commercial restrictions, pricing, subscriptions, or other access terms."""


class DocumentationBuilder(StrEnum):
    """Optional documentation site generator. An empty selection means documentation is plain Markdown."""

    mkdocs = "mkdocs"
    pkgdown = "pkgdown"
    sphinx = "sphinx"
    zensical = "zensical"


class Entry3(StrEnum):
    user = "user"
    deployment = "deployment"
    developer = "developer"


class DocumentationTypes(BaseModel):
    """SMP documentation categories the project provides. API and technical reference material are part of developer documentation."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry3]


class Entry4(StrEnum):
    contributing_md = "CONTRIBUTING.md"
    code_of_conduct_md = "CODE_OF_CONDUCT.md"
    governance_md = "GOVERNANCE.md"
    security_md = "SECURITY.md"
    support_md = "SUPPORT.md"
    changelog_md = "CHANGELOG.md"


class CommunityFiles(BaseModel):
    """Standard root community files the project provides. CONTRIBUTING.md and SUPPORT.md imply the corresponding GitHub collaboration files."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry4]


class Contacts(BaseModel):
    """Public contact routes for general community, code-of-conduct, and private security reports."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    community: str | None = None
    code_of_conduct: str | None = None
    security: str | None = None


class Entry5(StrEnum):
    smoke_tests = "Smoke tests"
    doctests = "Doctests"
    unit_tests = "Unit tests"
    integration_tests = "Integration tests"
    system___end_to_end_tests = "System / end-to-end tests"
    regression_tests = "Regression tests"
    property_based___fuzz = "Property-based / fuzz"


class TestTypes(BaseModel):
    """Types of tests used or desired. Supported values match the SMP testing checklist."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry5]


class Entry6(StrEnum):
    pytest = "pytest"
    unittest = "unittest"
    doctest = "doctest"
    testthat = "testthat"
    catch2 = "Catch2"
    google_test = "GoogleTest"
    cargo_test = "cargo test"
    j_unit_5 = "JUnit 5"
    vitest = "Vitest"
    jest = "Jest"
    bats_core = "bats-core"


class TestFrameworks(BaseModel):
    """Testing frameworks used by the project."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry6]


class Formatter(StrEnum):
    ruff = "ruff"
    black = "black"
    styler = "styler"
    prettier = "prettier"
    rustfmt = "rustfmt"
    clang_format = "clang-format"


class Linter(StrEnum):
    ruff = "ruff"
    flake8 = "flake8"
    pylint = "pylint"
    lintr = "lintr"
    eslint = "eslint"
    clippy = "clippy"
    clang_tidy = "clang-tidy"


class TypeChecker(StrEnum):
    mypy = "mypy"
    pyright = "pyright"
    basedpyright = "basedpyright"
    pyre = "pyre"
    tsc = "tsc"
    rustc = "rustc"
    flow = "Flow"


class QualityTools(BaseModel):
    """Optional primary formatter, linter, and static type checker."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    formatter: Formatter | None = None
    linter: Linter | None = None
    type_checker: TypeChecker | None = None


class ProjectManager(StrEnum):
    """Primary project and dependency manager, which determines setup, command execution, lockfile handling, and CI."""

    uv = "uv"
    poetry = "poetry"
    pdm = "pdm"
    hatch = "hatch"
    pixi = "pixi"
    pip = "pip"
    renv = "renv"
    rix = "rix"
    cargo = "cargo"
    npm = "npm"
    pnpm = "pnpm"
    yarn = "yarn"
    maven = "maven"
    gradle = "gradle"
    cmake = "cmake"


class Scheme(StrEnum):
    sem_ver = "SemVer"
    cal_ver = "CalVer"
    custom = "Custom"


class ReleaseFrequency(StrEnum):
    on_demand__irregular_as_needed_ = "On demand (irregular/as needed)"
    after_each_major_feature = "After each major feature"
    after_bug_fixes_or_patches = "After bug fixes or patches"
    on__fixed__schedule___automated = "On (fixed) schedule - automated"
    on__fixed__schedule = "On (fixed) schedule"
    single_release___no_updates = "Single release - no updates"


class Versioning(BaseModel):
    """Version value and public release policy. Empty properties leave the policy unspecified."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    version: str | None = None
    scheme: Scheme | None = None
    scheme_details: str | None = None
    release_frequency: ReleaseFrequency | None = None


class Entry7(StrEnum):
    py_pi = "PyPI"
    conda_forge = "conda-forge"
    cran = "CRAN"
    bioconductor = "Bioconductor"
    npm = "npm"
    crates_io = "crates.io"
    docker_hub = "Docker Hub"
    git_hub_container_registry = "GitHub Container Registry"
    quay = "Quay"
    apptainer_library = "Apptainer Library"
    bio_containers = "BioContainers"
    git_hub_releases = "GitHub Releases"
    zenodo = "Zenodo"
    institutional_archive = "Institutional archive"
    self_hosted_installer = "Self-hosted installer"
    hosted_service = "Hosted service"
    other = "Other"


class DistributionChannels(BaseModel):
    """Controlled public distribution routes, including package registries, releases, archives, installers, and hosted services."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry7]


class MaintenanceLevel(StrEnum):
    """Public maintenance commitment after active development winds down; leave empty when no commitment is declared."""

    active_routine_maintenance = "Active/routine maintenance"
    security_maintenance_only = "Security maintenance only"
    best_effort_maintenance___no_timeline_commitment = (
        "Best-effort maintenance / no timeline commitment"
    )


class Entry8(StrEnum):
    project_completed = "Project completed"
    replaced_by_successor_software = "Replaced by successor software"
    obsolete_technology___architecture = "Obsolete technology / architecture"
    incompatible_with_current_systems = "Incompatible with current systems"
    loss_or_end_of_funding = "Loss or end of funding"
    lack_of_maintainers = "Lack of maintainers"
    institutional_shift_in_priorities = "Institutional shift in priorities"
    retirement_of_critical_dependencies = "Retirement of critical dependencies"
    discontinuation_of_hosting___infrastructure = "Discontinuation of hosting / infrastructure"
    change_in_legal_or_regulatory_requirements = "Change in legal or regulatory requirements"
    security___privacy_risks = "Security / privacy risks"
    lack_of_user_demand_or_adoption = "Lack of user demand or adoption"
    declining_utility_or_relevance = "Declining utility or relevance"


class RetirementCriteria(BaseModel):
    """Public conditions under which the software may be retired."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry8]


class Entry9(StrEnum):
    gdpr___general_data_protection_regulation__eu_data_protection_ = (
        "GDPR - General Data Protection Regulation (EU data protection)"
    )
    mdr___ivdr___eu_medical_device_regulation___in_vitro_diagnostic_regulation = (
        "MDR / IVDR - EU Medical Device Regulation / In Vitro Diagnostic Regulation"
    )
    other_eu_or_national_regulations__e_g___dutch_wmo__data_processing_agreements_ = (
        "Other EU or National Regulations (e.g., Dutch WMO, data processing agreements)"
    )
    iso_iec_27001___information_security_management = (
        "ISO/IEC 27001 - Information Security Management"
    )
    iso_13485___quality_management_for_medical_devices = (
        "ISO 13485 - Quality Management for Medical Devices"
    )
    iso_iec_90003___software_engineering__guidelines_for_iso_9001_ = (
        "ISO/IEC 90003 - Software Engineering (guidelines for ISO 9001)"
    )
    iso_iec_12207___software_lifecycle_processes = "ISO/IEC 12207 - Software Lifecycle Processes"
    gx_p___good_clinical_practice = "GxP / Good Clinical Practice"
    ethical_approval___irb_requirements = "Ethical Approval / IRB Requirements"
    funding_programme_requirements__e_g___horizon_europe__nwo__elixir_ = (
        "Funding Programme Requirements (e.g., Horizon Europe, NWO, ELIXIR)"
    )
    institutional_security_policies = "Institutional Security Policies"
    departmental_sop__zenya___edr_ = "Departmental SOP (Zenya / EDR)"
    journal_data_software_availability_requirement = (
        "Journal data/software-availability requirement"
    )
    commissie_good_research_practice__grp_ = "Commissie Good Research Practice (GRP)"


class Selected(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry9]


class RegulatoryRequirements(BaseModel):
    """Controlled and additional public regulatory, quality, policy, or availability requirements."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    selected: Selected | None = None
    additional: str | None = None


class Entry10(StrEnum):
    user_authentication__e_g___password__o_auth__sso_ = (
        "User authentication (e.g., password, OAuth, SSO)"
    )
    role_based_access_control__rbac__or_permissions_system = (
        "Role-based access control (RBAC) or permissions system"
    )
    data_encryption_at_rest = "Data encryption at rest"
    data_encryption_in_transit__e_g___https_tls_ = "Data encryption in transit (e.g., HTTPS/TLS)"
    regular_dependency___library_updates = "Regular dependency / library updates"
    security_patch_management_process = "Security patch management process"
    vulnerability_scanning__e_g___snyk__dependabot_ = (
        "Vulnerability scanning (e.g., Snyk, Dependabot)"
    )
    secrets_management__e_g___environment_variables__vault_ = (
        "Secrets management (e.g., environment variables, vault)"
    )
    network_security__e_g___firewalls__vpn__isolated_subnets_ = (
        "Network security (e.g., firewalls, VPN, isolated subnets)"
    )
    secure_configuration_management__e_g___infrastructure_as_code__hardening_ = (
        "Secure configuration management (e.g., Infrastructure-as-Code, hardening)"
    )
    audit_logging___intrusion_detection = "Audit logging / intrusion detection"
    penetration_testing_or_security_review = "Penetration testing or security review"
    follows_institutional_or_regulatory_security_policies__e_g___iso_27001__nen_7510_ = (
        "Follows institutional or regulatory security policies (e.g., ISO 27001, NEN 7510)"
    )


class Selected1(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    entries: list[Entry10]


class SecurityMeasures(BaseModel):
    """Controlled and additional public security measures protecting the software and its data."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    selected: Selected1 | None = None
    additional: str | None = None


class DataManagement(BaseModel):
    """Public sensitive-data statement and DMP reference or contact route."""

    model_config = ConfigDict(
        extra="forbid",
        populate_by_name=True,
    )
    sensitive_data_statement: str | None = None
    dmp_reference: str | None = None


class Role(StrEnum):
    original_author = "Original author"
    co_author = "Co-author"
    maintainer = "Maintainer"
    successor = "Successor"
    principal_investigator = "Principal investigator"


[docs] class Organization(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] identifier: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None email: EmailStr | None = None url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None address: str | None = None
class FunderIdentifierType(StrEnum): """Identifier scheme used by funder_identifier.""" ror = "ror" crossref_funder_id = "crossref-funder-id" other = "other"
[docs] class Funding(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) funder: Annotated[str | None, Field(min_length=1)] = None funder_identifier: Annotated[str | None, Field(min_length=1)] = None """Stable identifier for the funder, such as a ROR ID or Crossref Funder ID.""" funder_identifier_type: FunderIdentifierType | None = None """Identifier scheme used by funder_identifier.""" funder_url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None """Public webpage for the funding organization.""" award_number: Annotated[str | None, Field(min_length=1)] = None award_title: Annotated[str | None, Field(min_length=1)] = None grant_url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None project_code: Annotated[str | None, Field(min_length=1)] = None
[docs] class RelatedSoftware(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str | None, Field(min_length=1)] = None url_or_doi: Annotated[str | None, Field(min_length=1)] = None relationship: str | None = None
[docs] class Registry(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] url_or_id: str | None = None notes: str | None = None
class Type1(StrEnum): doi = "doi" url = "url" swh = "swh" other = "other"
[docs] class PersistentIdentifier(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) type: Type1 identifier: Annotated[str, Field(min_length=1)] associated_version: str | None = None
[docs] class SupportRoute(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) system: Annotated[str, Field(min_length=1)] url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
[docs] class ProgrammingLanguage(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] version_constraint: str | None = None role: str | None = None
[docs] class DataFormat(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) term: Annotated[str | None, Field(min_length=1)] = None uri: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None version_constraint: str | None = None schema_constraints: str | None = None sample_url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
[docs] class EdamTerm(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) term: Annotated[str | None, Field(min_length=1)] = None uri: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
class Type2(StrEnum): bioinformatics_portal = "Bioinformatics portal" command_line_tool = "Command-line tool" database_portal = "Database portal" desktop_application = "Desktop application" library = "Library" ontology = "Ontology" plug_in = "Plug-in" script = "Script" sparql_endpoint = "SPARQL endpoint" suite = "Suite" web_application = "Web application" web_api = "Web API" web_service = "Web service" workbench = "Workbench" workflow = "Workflow" class Status(StrEnum): stable = "Stable" experimental = "Experimental" internal = "Internal"
[docs] class Interface(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) type: Type2 specification: str | None = None status: Status | None = None
class Name(StrEnum): linux = "Linux" mac_os = "macOS" windows = "Windows" i_os = "iOS" android = "Android" hpc_environments = "HPC environments" container = "Container" platform_independent = "Platform independent" other = "Other" class Status1(StrEnum): officially_supported = "Officially supported" expected_to_work = "Expected to work"
[docs] class OperatingSystem(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Name specification: str | None = None status: Status1 | None = None
[docs] class ExternalDependency(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] version_constraint: str | None = None url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None license: str | None = None purpose: str | None = None
class ServiceType(StrEnum): institutional_support__dcc__it__library_ = "Institutional support (DCC, IT, library)" hosted_compute___storage = "Hosted compute / storage" ci___cd_minutes = "CI / CD minutes" saa_s_subscription = "SaaS subscription" legal___contractual = "Legal / contractual" external_review_or_audit = "External review or audit" domain_expertise = "Domain expertise" other = "Other" class CostCoverageEnum(StrEnum): project_budget = "Project budget" departmental_overhead = "Departmental overhead" external_grant = "External grant" free_tier = "Free tier" in_kind___unfunded = "In-kind / unfunded"
[docs] class ExternalService(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] provider: str | None = None service_types: list[ServiceType] | None = None quantity: str | None = None cost_coverage: list[CostCoverageEnum] | None = None
class Type3(StrEnum): docker = "Docker" oci___podman = "OCI / Podman" apptainer___singularity = "Apptainer / Singularity" other = "Other"
[docs] class Containerization(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) type: Type3 details: str | None = None
class Topics(BaseModel): """Research domains the software applies to, as EDAM topic terms. Entries may include term and uri. Broader and controlled where keywords are free text.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[EdamTerm] class FundingModel(BaseModel): """Public funding records. Entries may include funder, funder identifiers and URLs, award_number, award_title, grant_url, and project_code.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Funding] class RelatedSoftwareModel(BaseModel): """Related or upstream tools. Entries may include name, url_or_doi, and relationship.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[RelatedSoftware] class Registries(BaseModel): """Registry entries such as PyPI, CRAN, bio.tools, WorkflowHub, or institutional catalogues. Entries may include name, url_or_id, and notes.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Registry] class PersistentIdentifiers(BaseModel): """Persistent identifiers. Each entry declares its CFF identifier type and value, with an optional associated version.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[PersistentIdentifier] class SupportRoutes(BaseModel): """Public support, bug-reporting, or feature-request systems and their public URLs.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[SupportRoute] class ProgrammingLanguages(BaseModel): """Programming languages used by the project. Entries include a name and may include version_constraint and role from the SMP.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[ProgrammingLanguage] class Interfaces(BaseModel): """Interfaces exposed by the software. Type names the interface; specification and status describe it.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Interface] class OperatingSystems(BaseModel): """Supported operating systems or platforms. Entries may include name, specification, and status from the SMP.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[OperatingSystem] class ExternalDependencies(BaseModel): """External software dependencies or standards. Entries may include name, version_constraint, url, license, and purpose.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[ExternalDependency] class ExternalServices(BaseModel): """External public services, partners, or roles needed by the project. Entries may include name, provider, service_types, quantity, and cost_coverage.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[ExternalService] class ContainerizationModel(BaseModel): """Container recipes the project ships. Project managers and lockfiles are declared separately.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Containerization]
[docs] class Person(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) name: Annotated[str, Field(min_length=1)] given_names: Annotated[str | None, Field(min_length=1)] = None family_names: Annotated[str | None, Field(min_length=1)] = None email: EmailStr | None = None affiliations: list[Organization] | None = None """Organizations the person is affiliated with, most relevant first.""" orcid: str | None = None roles: list[Role] | None = None url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None
[docs] class Contributor(Person): model_config = ConfigDict( populate_by_name=True, ) roles: Annotated[list[Role], Field(min_length=1)]
[docs] class Publication(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) title: Annotated[str | None, Field(min_length=1)] = None type: str | None = None doi: Annotated[str | None, Field(min_length=1)] = None pmid: Annotated[str | None, Field(min_length=1)] = None pmcid: Annotated[str | None, Field(min_length=1)] = None url: Annotated[str | None, Field(pattern="^(?:[A-Za-z][A-Za-z0-9+.-]*:.*)?$")] = None citation: Annotated[str | None, Field(min_length=1)] = None note: str | None = None preferred: bool | None = None authors: list[Person] | None = None
[docs] class FunctionIo(BaseModel): model_config = ConfigDict( extra="forbid", populate_by_name=True, ) data: EdamTerm | None = None format: list[DataFormat] | None = None
class Contributors(BaseModel): """Everyone credited for the software, each entry declaring one or more roles. Name and roles are required; entries may also include given_names, family_names, email, affiliations, orcid, and url. A non-empty list must credit at least one author, which is what citation metadata requires.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Contributor] class Publications(BaseModel): """Associated publications. Entries may include title, type, authors, doi, pmid, pmcid, url, citation, note, and preferred.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[Publication]
[docs] class SoftwareFunction(BaseModel): """Functions or operations performed by the software. Entries may include operations, inputs, outputs, cmd, and note.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) operations: list[EdamTerm] | None = None inputs: list[FunctionIo] | None = None outputs: list[FunctionIo] | None = None cmd: str | None = None note: str | None = None
class SoftwareFunctions(BaseModel): """Functions or operations performed by the software. Entries may include operations, inputs, outputs, cmd, and note.""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) entries: list[SoftwareFunction]
[docs] class RSMMetadata(BaseModel): """Structured metadata for research software management (RSM).""" model_config = ConfigDict( extra="forbid", populate_by_name=True, ) project_name: str | None = None """Human-readable project title.""" project_slug: str """Machine-readable package and repository name. Consumers apply their own additional slug constraints.""" project_short_description: str | None = None """One-sentence description used in README and package metadata.""" project_long_description: str | None = None """Longer public description of the project motivation and scope.""" development_status: DevelopmentStatus | None = None """Current repostatus.org lifecycle status for the software.""" topics: Annotated[Topics, Field(validate_default=True)] = {"entries": []} """Research domains the software applies to, as EDAM topic terms. Entries may include term and uri. Broader and controlled where keywords are free text.""" keywords: Annotated[Keywords, Field(validate_default=True)] = {"entries": []} """Public keywords used in package metadata, citation metadata, registries, and archives.""" contributors: Annotated[Contributors, Field(validate_default=True)] = {"entries": []} """Everyone credited for the software, each entry declaring one or more roles. Name and roles are required; entries may also include given_names, family_names, email, affiliations, orcid, and url. A non-empty list must credit at least one author, which is what citation metadata requires.""" funding: Annotated[FundingModel, Field(validate_default=True)] = {"entries": []} """Public funding records. Entries may include funder, funder identifiers and URLs, award_number, award_title, grant_url, and project_code.""" motivation: Annotated[Motivation, Field(validate_default=True)] = { "categories": {"entries": []} } """Public purpose, purpose categories, problem statement, and value proposition.""" audiences: Annotated[Audiences, Field(validate_default=True)] = {"entries": []} """Intended users or stakeholder groups.""" related_software: Annotated[RelatedSoftwareModel, Field(validate_default=True)] = { "entries": [] } """Related or upstream tools. Entries may include name, url_or_doi, and relationship.""" urls: Annotated[Urls, Field(validate_default=True)] = {} """Canonical source repository, project homepage, and published documentation URLs.""" registries: Annotated[Registries, Field(validate_default=True)] = {"entries": []} """Registry entries such as PyPI, CRAN, bio.tools, WorkflowHub, or institutional catalogues. Entries may include name, url_or_id, and notes.""" persistent_identifiers: Annotated[PersistentIdentifiers, Field(validate_default=True)] = { "entries": [] } """Persistent identifiers. Each entry declares its CFF identifier type and value, with an optional associated version.""" publications: Annotated[Publications, Field(validate_default=True)] = {"entries": []} """Associated publications. Entries may include title, type, authors, doi, pmid, pmcid, url, citation, note, and preferred.""" licensing: Annotated[Licensing, Field(validate_default=True)] = {} """License text or SPDX identifier and the selected dependency-license compatibility method.""" access: Annotated[Access, Field(validate_default=True)] = {} """How users can obtain or use the software, independently of its copyright license.""" include_metadata: bool = False """Whether the project publishes CodeMeta and Citation File Format metadata files alongside their validation workflow.""" documentation_builder: DocumentationBuilder | None = None """Optional documentation site generator. An empty selection means documentation is plain Markdown.""" documentation_types: Annotated[DocumentationTypes, Field(validate_default=True)] = { "entries": [] } """SMP documentation categories the project provides. API and technical reference material are part of developer documentation.""" community_files: Annotated[CommunityFiles, Field(validate_default=True)] = {"entries": []} """Standard root community files the project provides. CONTRIBUTING.md and SUPPORT.md imply the corresponding GitHub collaboration files.""" code_review_policy: Annotated[ str | None, Field(json_schema_extra={"contentMediaType": "text/markdown"}) ] = None """Public code-review policy for proposed changes, including reviewer expectations, approval requirements, and merge conditions. Markdown is supported.""" support_routes: Annotated[SupportRoutes, Field(validate_default=True)] = {"entries": []} """Public support, bug-reporting, or feature-request systems and their public URLs.""" contacts: Annotated[Contacts, Field(validate_default=True)] = {} """Public contact routes for general community, code-of-conduct, and private security reports.""" governance_notes: str | None = None """Public governance and decision-making notes.""" programming_languages: Annotated[ProgrammingLanguages, Field(validate_default=True)] = { "entries": [] } """Programming languages used by the project. Entries include a name and may include version_constraint and role from the SMP.""" software_functions: Annotated[SoftwareFunctions, Field(validate_default=True)] = {"entries": []} """Functions or operations performed by the software. Entries may include operations, inputs, outputs, cmd, and note.""" interfaces: Annotated[Interfaces, Field(validate_default=True)] = {"entries": []} """Interfaces exposed by the software. Type names the interface; specification and status describe it.""" operating_systems: Annotated[OperatingSystems, Field(validate_default=True)] = {"entries": []} """Supported operating systems or platforms. Entries may include name, specification, and status from the SMP.""" external_dependencies: Annotated[ExternalDependencies, Field(validate_default=True)] = { "entries": [] } """External software dependencies or standards. Entries may include name, version_constraint, url, license, and purpose.""" external_services: Annotated[ExternalServices, Field(validate_default=True)] = {"entries": []} """External public services, partners, or roles needed by the project. Entries may include name, provider, service_types, quantity, and cost_coverage.""" test_types: Annotated[TestTypes, Field(validate_default=True)] = {"entries": []} """Types of tests used or desired. Supported values match the SMP testing checklist.""" test_frameworks: Annotated[TestFrameworks, Field(validate_default=True)] = {"entries": []} """Testing frameworks used by the project.""" quality_tools: Annotated[QualityTools, Field(validate_default=True)] = {} """Optional primary formatter, linter, and static type checker.""" project_manager: ProjectManager | None = None """Primary project and dependency manager, which determines setup, command execution, lockfile handling, and CI.""" versioning: Annotated[Versioning, Field(validate_default=True)] = {} """Version value and public release policy. Empty properties leave the policy unspecified.""" distribution_channels: Annotated[DistributionChannels, Field(validate_default=True)] = { "entries": [] } """Controlled public distribution routes, including package registries, releases, archives, installers, and hosted services.""" containerization: Annotated[ContainerizationModel, Field(validate_default=True)] = { "entries": [] } """Container recipes the project ships. Project managers and lockfiles are declared separately.""" resource_requirements: str | None = None """Public typical and worst-case memory, storage, compute, GPU, wall-clock, or scaling requirements.""" maintenance_level: MaintenanceLevel | None = None """Public maintenance commitment after active development winds down; leave empty when no commitment is declared.""" continuity_plan: str | None = None """Public continuity or handover plan.""" retirement_criteria: Annotated[RetirementCriteria, Field(validate_default=True)] = { "entries": [] } """Public conditions under which the software may be retired.""" public_risk_notes: str | None = None """Public risk or mitigation notes. Sensitive security, privacy, or compliance details should not be included.""" regulatory_requirements: Annotated[RegulatoryRequirements, Field(validate_default=True)] = { "selected": {"entries": []} } """Controlled and additional public regulatory, quality, policy, or availability requirements.""" security_measures: Annotated[SecurityMeasures, Field(validate_default=True)] = { "selected": {"entries": []} } """Controlled and additional public security measures protecting the software and its data.""" data_management: Annotated[DataManagement, Field(validate_default=True)] = {} """Public sensitive-data statement and DMP reference or contact route."""