diff --git a/libcove2/common.py b/libcove2/common.py index ea7e80d..0f03332 100644 --- a/libcove2/common.py +++ b/libcove2/common.py @@ -11,11 +11,49 @@ "^(.*_(((([A-Za-z]{2,3}(-([A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-([A-Za-z]{4}))?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-([0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(x(-[A-Za-z0-9]{1,8})+))?)|(x(-[A-Za-z0-9]{1,8})+)))$" # noqa ) +def process_items(schema_dict, registry=None, defs=None): + items_schema_dicts = [] + if "oneOf" in schema_dict["items"] and isinstance( + schema_dict["items"]["oneOf"], list + ): + for oneOf in schema_dict["items"]["oneOf"]: + items_schema_dicts.append(oneOf) + elif '$ref' in schema_dict["items"]: + if schema_dict["items"]['$ref'].startswith('urn:'): + subschema = registry.contents(schema_dict["items"]['$ref'].split("#")[0]) + if '#/$defs/' in schema_dict["items"]['$ref']: + name = schema_dict["items"]['$ref'].split('$defs/')[-1] + defs = subschema['$defs'] + subschema = defs[name] + items_schema_dicts.append(subschema) + elif schema_dict["items"]['$ref'].startswith('#/$defs/'): + name = schema_dict["items"]['$ref'].split('$defs/')[-1] + items_schema_dicts.append(defs[name]) + elif "properties" in schema_dict["items"] and isinstance( + schema_dict["items"]["properties"], dict + ): + items_schema_dicts.append(schema_dict["items"]) + return items_schema_dicts -def schema_dict_fields_generator(schema_dict): +def schema_dict_fields_generator(schema_dict, registry=None, defs=None): + if '$defs' in schema_dict: + defs = schema_dict['$defs'] if "properties" in schema_dict and isinstance(schema_dict["properties"], dict): for property_name, value in schema_dict["properties"].items(): - if "oneOf" in value: + if '$ref' in value: + if value['$ref'].startswith('urn:'): + property_schema_dicts = registry.contents(value['$ref'].split('#')[0]) + if '$defs/' in value['$ref']: + name = value['$ref'].split('$defs/')[-1] + property_schema_dicts = property_schema_dicts['$defs'][name] + else: + name = value['$ref'].split('$defs/')[-1] + property_schema_dicts = defs[name] + property_schema_dicts = [property_schema_dicts] + elif ("items" in value and isinstance(value["items"], dict) and + (not "type" in value["items"] or value["items"]["type"] == "object")): + property_schema_dicts = process_items(value, registry=registry, defs=defs) + elif "oneOf" in value: property_schema_dicts = value["oneOf"] else: property_schema_dicts = [value] @@ -23,22 +61,25 @@ def schema_dict_fields_generator(schema_dict): if not isinstance(property_schema_dict, dict): continue if "properties" in property_schema_dict: - for field in schema_dict_fields_generator(property_schema_dict): + for field in schema_dict_fields_generator(property_schema_dict, registry=registry, defs=defs): yield f"/{property_name}{field}" elif "items" in property_schema_dict: for field in schema_dict_fields_generator( - property_schema_dict["items"] + property_schema_dict["items"], registry=registry, defs=defs ): yield f"/{property_name}{field}" yield f"/{property_name}" - if "items" in schema_dict and isinstance(schema_dict["items"], dict): - if "oneOf" in schema_dict["items"] and isinstance( - schema_dict["items"]["oneOf"], list - ): - for oneOf in schema_dict["items"]["oneOf"]: - for field in schema_dict_fields_generator(oneOf): + if "allOf" in schema_dict and isinstance(schema_dict["allOf"], list): + for clause in schema_dict["allOf"]: + if "then" in clause and isinstance(clause["then"], dict): + for field in schema_dict_fields_generator(clause["then"], registry=registry, defs=defs): yield field - + if ("items" in schema_dict and isinstance(schema_dict["items"], dict) and + (not "type" in schema_dict["items"] or schema_dict["items"]["type"] == "object")): + items_schema_dicts = process_items(schema_dict, registry=registry, defs=defs) + for items_schema_dict in items_schema_dicts: + for field in schema_dict_fields_generator(items_schema_dict, registry=registry, defs=defs): + yield field def get_additional_fields_info(json_data, schema_fields, fields_regex=False): fields_present = get_fields_present_with_examples(json_data) diff --git a/tests/fixtures/bods-data-0-3-0.json b/tests/fixtures/bods-data-0-3-0.json new file mode 100644 index 0000000..8fddefc --- /dev/null +++ b/tests/fixtures/bods-data-0-3-0.json @@ -0,0 +1,102 @@ +[ + { + "statementID": "1dc0e987-5c57-4a1c-b3ad-61353b66a9b7", + "statementType": "entityStatement", + "isComponent": false, + "statementDate": "2017-11-18", + "entityType": "registeredEntity", + "name": "CHRINON LTD", + "foundingDate": "2010-11-18", + "identifiers": [ + { + "scheme": "GB-COH", + "id": "07444723" + } + ], + "publicListing": { + "hasPublicListing": true, + "companyFilingsURLs": ["http://example.com/"], + "securitiesListings": [] + }, + "publicationDetails": { + "publicationDate": "2018-02-13", + "bodsVersion": "0.3", + "publisher": { + "name": "CHRINON LTD" + } + } + }, + { + "statementID": "019a93f1-e470-42e9-957b-03559861b2e2", + "statementType": "personStatement", + "isComponent": false, + "statementDate": "2017-11-18", + "personType": "knownPerson", + "nationalities": [ + { + "code": "GB", + "name": "United Kingdom of Great Britain and Northern Ireland (the)" + } + ], + "names": [ + { + "type": "individual", + "fullName": "Christopher Taggart", + "givenName": "Christopher", + "familyName": "Taggart" + }, + { + "type": "alternative", + "fullName": "Chris Taggart" + } + ], + "birthDate": "1964-04", + "addresses": [ + { + "type": "service", + "address": "Aston House, Cornwall Avenue, London", + "country": "GB", + "postCode": "N3 1LF" + } + ], + "publicationDetails": { + "publicationDate": "2018-02-13", + "bodsVersion": "0.3", + "publisher": { + "name": "CHRINON LTD" + } + } + }, + { + "statementID": "fbfd0547-d0c6-4a00-b559-5c5e91c34f5c", + "statementType": "ownershipOrControlStatement", + "isComponent": false, + "statementDate": "2017-11-18", + "subject": { + "describedByEntityStatement": "1dc0e987-5c57-4a1c-b3ad-61353b66a9b7" + }, + "interestedParty": { + "describedByPersonStatement": "019a93f1-e470-42e9-957b-03559861b2e2" + }, + "interests": [ + { + "type": "shareholding", + "directOrIndirect": "direct", + "beneficialOwnershipOrControl": true, + "startDate": "2016-04-06", + "share": { + "exact": 100, + "minimum": 100, + "maximum": 100 + } + } + ], + "publicationDetails": { + "publicationDate": "2018-02-13", + "bodsVersion": "0.3", + "publisher": { + "name": "CHRINON LTD" + } + } + } +] \ No newline at end of file diff --git a/tests/fixtures/bods-data-0-4-0.json b/tests/fixtures/bods-data-0-4-0.json new file mode 100644 index 0000000..adec741 --- /dev/null +++ b/tests/fixtures/bods-data-0-4-0.json @@ -0,0 +1,111 @@ +[ + { + "statementId": "1dc0e987-5c57-4a1c-b3ad-61353b66a9b7", + "declarationSubject": "c359f58d2977", + "statementDate": "2020-03-04", + "publicationDetails": { + "publicationDate": "2020-03-04", + "bodsVersion": "0.4", + "publisher": { + "name": "Profitech Ltd" + } + }, + "recordId": "c359f58d2977", + "recordStatus": "new", + "recordType": "entity", + "recordDetails": { + "isComponent": false, + "entityType": { + "type": "registeredEntity" + }, + "name": "Profitech Ltd", + "foundingDate": "2019-09-03", + "identifiers": [ + { + "scheme": "GB-COH", + "id": "2063384560" + } + ] + } + }, + { + "statementId": "019a93f1-e470-42e9-957b-03559861b2e2", + "declarationSubject": "c359f58d2977", + "statementDate": "2020-03-04", + "publicationDetails": { + "publicationDate": "2020-03-04", + "bodsVersion": "0.4", + "publisher": { + "name": "Profitech Ltd" + } + }, + "recordId": "10478c6cf6de", + "recordStatus": "new", + "recordType": "person", + "recordDetails": { + "isComponent": false, + "personType": "knownPerson", + "nationalities": [ + { + "code": "GB", + "name": "United Kingdom of Great Britain and Northern Ireland (the)" + } + ], + "names": [ + { + "type": "legal", + "fullName": "Jennifer Hewitson-Smith", + "givenName": "Jennifer", + "familyName": "Hewitson-Smith" + }, + { + "type": "alternative", + "fullName": "Jenny Hewitson-Smith" + } + ], + "birthDate": "1978-07", + "addresses": [ + { + "type": "service", + "address": "76 York Road Bournemouth", + "postCode": "BH81 3LO", + "country": { + "name": "United Kingdom", + "code": "GB" + } + } + ] + } + }, + { + "statementId": "fbfd0547-d0c6-4a00-b559-5c5e91c34f5c", + "declarationSubject": "c359f58d2977", + "statementDate": "2020-03-04", + "publicationDetails": { + "publicationDate": "2020-03-04", + "bodsVersion": "0.4", + "publisher": { + "name": "Profitech Ltd" + } + }, + "recordId": "93b53022ae6a", + "recordStatus": "new", + "recordType": "relationship", + "recordDetails": { + "isComponent": false, + "subject": "c359f58d2977", + "interestedParty": "10478c6cf6de", + "interests": [ + { + "type": "shareholding", + "beneficialOwnershipOrControl": true, + "directOrIndirect": "direct", + "startDate": "2016-04-06", + "share": { + "exact": 100 + } + } + ] + } + } +] diff --git a/tests/fixtures/schema-0-3-0.json b/tests/fixtures/schema-0-3-0.json new file mode 100644 index 0000000..7dbf9e9 --- /dev/null +++ b/tests/fixtures/schema-0-3-0.json @@ -0,0 +1,1945 @@ +{ + "id": "bods-package.json", + "$schema": "http://json-schema.org/draft-04/schema#", + "version": "0.3", + "type": "array", + "items": { + "oneOf": [ + { + "id": "entity-statement.json", + "$schema": "http://json-schema.org/draft-04/schema#", + "version": "0.3", + "title": "Entity statement", + "description": "A statement identifying and describing the entity that is the subject of the ownership or control described in an ownership or control statement.", + "type": "object", + "properties": { + "statementID": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this statement.", + "type": "string", + "minLength": 32, + "maxLength": 64, + "propertyOrder": 1 + }, + "statementType": { + "title": "Statement type", + "description": "This MUST be 'entityStatement'.", + "type": "string", + "enum": [ + "entityStatement" + ], + "propertyOrder": 2 + }, + "statementDate": { + "title": "Statement date", + "description": "The date on which this statement was made.", + "type": "string", + "format": "date", + "propertyOrder": 3 + }, + "isComponent": { + "title": "Is component", + "description": "Does this Entity Statement represent a component of an indirect ownership-or-control relationship? Where `isComponent` is 'true': (1) the `statementID` of this Entity Statement MUST be an element in the `componentStatementIDs` array of that primary Ownership-or-control Statement, (2) this Entity Statement MUST come before that primary Ownership-or-control Statement in a BODS package or stream, (3) the replacement of this Entity Statement SHOULD be considered when replacing the primary Ownership-or-control Statement. The primary Ownership-or-control Statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "entityType": { + "title": "Type", + "description": "From the entityType codelist. What kind of entity is this? The 'registeredEntity' code covers any legal entity created through an act of official registration, usually resulting in an identifier being assigned to the entity. The \u2018legalEntity\u2019 code covers other bodies with distinct legal personality (international institutions, statutory corporations etc.). The 'arrangement' code covers artificial entities, described in the data model for the purpose of associating one or more natural or legal persons together in an ownership or control relationship, but without implying that the parties to this arrangement have any other form of collective legal identity.", + "type": "string", + "enum": [ + "registeredEntity", + "legalEntity", + "arrangement", + "anonymousEntity", + "unknownEntity", + "state", + "stateBody" + ], + "codelist": "entityType.csv", + "openCodelist": false, + "propertyOrder": 4 + }, + "unspecifiedEntityDetails": { + "title": "Unspecified entity details", + "description": "An explanation of why this entity has an `entityType` of 'anonymousEntity' or 'unknownEntity'. A `reason` MUST be specified.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that an entity cannot be specified. From the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Any supporting information about the absence of a specific entity. This field may be used to provide set phrases from a source system, or for a free-text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "propertyOrder": 8 + }, + "name": { + "title": "Entity name", + "description": "The declared name of this entity.", + "type": "string", + "propertyOrder": 10 + }, + "alternateNames": { + "title": "Alternative names", + "description": "An array of other names this entity is known by.", + "type": "array", + "items": { + "type": "string", + "title": "Name", + "description": "A name this entity is known by." + }, + "propertyOrder": 12 + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "The jurisdiction in which this entity was registered (for legal and registered entities, and arrangements). Or the state's jurisdiction (for states and state bodies).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or subdivision code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ], + "propertyOrder": 15 + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this entity. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to this person or entity. The scheme or list from which the identifier is drawn should be declared.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for this person or entity as provided in the declared scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme", + "description": "For entity statements, the scheme should be a entry from the org-id.guide (https://www.org-id.guide) codelist. For person statements, the scheme should have the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "string" + }, + "schemeName": { + "title": "Scheme name", + "description": "The name of this scheme, where the org-id code is unknown or only an unvalidated string is provided. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "Where this identifier has a canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) this may be included", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "foundingDate": { + "title": "Founding date", + "description": "When was this entity founded, created or registered. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$", + "propertyOrder": 30 + }, + "dissolutionDate": { + "title": "Dissolution date", + "description": "If this entity is no longer active, provide the date on which it was disolved or ceased. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$", + "propertyOrder": 35 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this entity.", + "type": "array", + "items": { + "title": "Address", + "description": "A free text address string, providing as much address data as is relevant, suitable for processing using address parsing algorithms. For some uses (for example, Place of Birth) only a town and country are required.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "What type of address is this? See the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component of the address separated by a line-break or comma. Where postal codes are isolated fields in source systems, this `address` field SHOULD NOT include the postal code.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "The 2-letter country code (ISO 3166-1) for this address.", + "type": "string", + "minLength": 2, + "maxLength": 2 + } + } + }, + "propertyOrder": 40 + }, + "uri": { + "title": "URI", + "description": "Where a persistent URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) is available for this entity this should be included.", + "type": "string", + "format": "uri", + "propertyOrder": 21 + }, + "replacesStatements": { + "title": "Replaces statement(s)", + "description": "If this statement replaces a previous statement or statements, provide the identifier(s) for the previous statement(s) here. Consuming applications are advised to mark the identified statements as no longer active.", + "type": "array", + "items": { + "title": "Statement identifier", + "description": "The identifier of a statement that is no longer active.", + "type": "string", + "minLength": 32, + "maxLength": 64 + }, + "propertyOrder": 100 + }, + "publicationDetails": { + "title": "Publication details", + "description": "Information concerning the original publication of this statement.", + "type": "object", + "properties": { + "publicationDate": { + "title": "Publication date", + "description": "The date on which this statement was published.", + "type": "string", + "format": "date" + }, + "bodsVersion": { + "title": "BODS version", + "description": "The version of the Beneficial Ownership Data Standard to which this statement conforms, expressed as major.minor. For example: 0.2 or 1.0.", + "type": "string", + "pattern": "^(\\d+\\.)(\\d+)$" + }, + "license": { + "title": "License URL", + "description": "A link to the license that applies to this statement. The canonical URI of the license SHOULD be used. Publishers are encouraged to use a Public Domain Dedication or Open Definition Conformant (http://opendefinition.org/licenses/) license.", + "type": "string", + "format": "uri" + }, + "publisher": { + "type": "object", + "title": "Publisher", + "description": "Details of the organisation or individual publishing this statement.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the publisher", + "type": "string" + }, + "url": { + "title": "URL", + "description": "The URL of the parent dataset or of the publisher's website homepage", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "url" + ] + } + ] + } + }, + "required": [ + "publicationDate", + "bodsVersion", + "publisher" + ], + "propertyOrder": 85 + }, + "source": { + "title": "Source", + "description": "The source of information about this entity, or of information that supports an anonymous or unknown entity statement.", + "type": "object", + "properties": { + "type": { + "title": "Source type", + "description": "What type of source is this? Multiple tags can be combined. Values should come from the source type codelist.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Where required, additional free-text information about the source of this statement can be provided here.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "If this information was fetched from an external URL, or a machine or human readable web page is available that provides additional information on how this statement was sourced, provide the URL.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved at", + "description": "If this statement was imported from some external system, include a timestamp indicating when this took place. The statement's own date should be set based on the source information. ", + "type": "string", + "format": "date-time" + }, + "assertedBy": { + "title": "Asserted by", + "description": "Who is making this statement? This may be the name of the person or organisation making a self-declaration (in which case, please make sure the name field matches the organisation or person name field), or the name or description of some other party. If this statement has been verified, this may also include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "title": "Agent", + "description": "An individual, organisation or other responsible agent making, or supporting, a given statement or annotation.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent.", + "type": "string", + "format": "uri" + } + } + } + } + }, + "propertyOrder": 89 + }, + "annotations": { + "title": "Annotations", + "description": "Annotations about this statement or parts of this statement", + "type": "array", + "items": { + "title": "Annotation", + "description": "An annotation provides additional information about ownership or control data being provided. Annotations can be provided in free-text, and can apply to a whole statement, an object or a single field. Additional extended properties can be included on the annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this annotation applies to, starting from the root of the statement. A value of '/' indicates that the annotation applies to the whole statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date this annotation was created.", + "type": "string", + "format": "date" + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify person, organisation or agent that created this annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The motivation for this annotation, chosen from a codelist. See the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free-text description to annotate this statement or field.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed content", + "description": "A representation of the annotation target after the transformation in the description field has been applied. This field SHOULD only be used when the motivation is transformation." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "required": [ + "statementPointerTarget", + "motivation" + ], + "oneOfEnumSelectorField": "motivation", + "oneOf": [ + { + "properties": { + "motivation": { + "enum": [ + "linking" + ] + } + }, + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + { + "properties": { + "motivation": { + "enum": [ + "identifying", + "commenting", + "correcting", + "transformation" + ] + } + } + } + ] + }, + "propertyOrder": 90 + }, + "publicListing": { + "type": "object", + "title": "Public listing", + "description": "Details of a publicly listed company, its securities (shares and other tradable financial instruments related to the entity), and related regulatory filings.", + "required": [ + "securitiesListings", + "hasPublicListing" + ], + "minProperties": 1, + "properties": { + "hasPublicListing": { + "type": "boolean", + "title": "Has public listing", + "description": "This value MUST be true if the entity is known to be a publicly listed company." + }, + "companyFilingsURLs": { + "type": "array", + "title": "Company filings URLs", + "description": "URL or URLs where regulatory filings related to major holdings can be retrieved. URLs may point to pages maintained by regulatory bodies, stock exchanges or by the company itself.", + "items": { + "type": "string" + }, + "format": "uri" + }, + "securitiesListings": { + "type": "array", + "title": "Securities listings", + "description": "Details of the entity's securities and the public exchanges and markets on which they are traded. All equity securities SHOULD BE listed here, plus any other securities from which beneficial ownership might be derived. Where a security is traded on more than one market, there SHOULD BE an entry for each market (or market segment).", + "items": { + "type": "object", + "title": "Securities listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock exchange jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock exchange name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier. For accepted schemas, see the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + }, + "entitySubtype": { + "type": "object", + "title": "Subtype", + "description": "Further information about the type of entity described in the statement.", + "required": [ + "generalCategory" + ], + "properties": { + "generalCategory": { + "type": "string", + "title": "General category", + "description": "The general category into which the entity fits. The category classification MUST align with the `entityType` classification.", + "codelist": "entitySubtypeCategory.csv", + "enum": [ + "stateBody-governmentDepartment", + "stateBody-stateAgency", + "stateBody-other" + ], + "openCodelist": false + }, + "localTerm": { + "type": "string", + "title": "Local term", + "description": "The local term for the category of entity. For example, in Finland 'ministeri\u00f6' for a government department." + } + }, + "propertyOrder": 5 + }, + "formedByStatute": { + "type": "object", + "title": "Formed by statute", + "description": "The law which mandated the formation of the entity described in the statement, where applicable. This information SHOULD be provided where a state has created an agency or other entity with specific legislation. ", + "properties": { + "name": { + "type": "string", + "title": "Statute name", + "description": "The name of the law. " + }, + "date": { + "type": "string", + "title": "Date", + "description": "The date on which the law was passed. The date SHOULD be in the form YYYY-MM-DD. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$" + } + }, + "propertyOrder": 18 + } + }, + "required": [ + "statementID", + "statementType", + "isComponent", + "entityType", + "publicationDetails" + ] + }, + { + "id": "person-statement.json", + "$schema": "http://json-schema.org/draft-04/schema#", + "version": "0.3", + "type": "object", + "title": "Person statement", + "description": "A person statement describes the information known about a natural person at a particular point in time, or from a given submission of information", + "properties": { + "statementID": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this statement.", + "type": "string", + "minLength": 32, + "maxLength": 64, + "propertyOrder": 1 + }, + "statementType": { + "title": "Statement type", + "description": "This MUST be 'personStatement'.", + "type": "string", + "enum": [ + "personStatement" + ], + "propertyOrder": 2 + }, + "statementDate": { + "title": "Statement date", + "description": "The date on which this statement was made.", + "type": "string", + "format": "date", + "propertyOrder": 3 + }, + "isComponent": { + "title": "Is component", + "description": "Does this Person Statement represent a component of an indirect ownership-or-control relationship? Where `isComponent` is 'true': (1) the `statementID` of this Person Statement MUST be an element in the `componentStatementIDs` array of that primary Ownership-or-control Statement, (2) this Person Statement MUST come before that primary Ownership-or-control Statement in a BODS package or stream, (3) the replacement of this Person Statement SHOULD be considered when replacing the primary Ownership-or-control Statement. The primary Ownership-or-control Statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "personType": { + "title": "Person type", + "description": "Use the personType codelist. The ultimate beneficial owner of a legal entity is always a natural person. Where the beneficial owner has been identified, but information about them cannot be disclosed, use 'anonymousPerson'. Where the beneficial owner has not been clearly identified, use 'unknownPerson'. Where the beneficial owner has been identified use knownPerson. Where a person has the type 'anonymousPerson' or 'unknownPerson' a reason for the absence of information SHOULD be provided in 'unspecifiedPersonDetails')", + "type": "string", + "enum": [ + "knownPerson", + "anonymousPerson", + "unknownPerson" + ], + "propertyOrder": 4, + "codelist": "personType.csv", + "openCodelist": false + }, + "unspecifiedPersonDetails": { + "title": "Unspecified person details", + "description": "An explanation of why this person has a `personType` of 'anonymousPerson' or 'unknownPerson'. A `reason` MUST be specified.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that an interested party cannot be specified. From the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Any supporting information about the absence of a confirmed beneficial owner. This field may be used to provide set phrases from a source system, or for a free-text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "propertyOrder": 5 + }, + "names": { + "title": "Names", + "description": "One or more known names for this individual.", + "type": "array", + "items": { + "title": "Name", + "description": "An name by which this individual is known. Names should be provided in `fullName`, and may optionally be broken down in the `familyName`, `givenName` and `patronymicName` fields, based on the EC ISA Core Person Vocabulary (https://joinup.ec.europa.eu/solution/e-government-core-vocabularies) definitions.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "What kind of name is this? See the nameType codelist.", + "type": "string", + "enum": [ + "individual", + "translation", + "transliteration", + "former", + "alternative", + "birth" + ], + "codelist": "nameType.csv", + "openCodelist": false + }, + "fullName": { + "title": "Full name", + "description": "The full name contains the complete name of a person as one string.", + "type": "string" + }, + "familyName": { + "title": "Family name", + "description": "A family name is usually shared by members of a family. This attribute also carries prefixes or suffixes which are part of the Family Name, e.g. 'de Boer', 'van de Putte', 'von und zu Orlow'. Multiple family names, such as are commonly found in Hispanic countries, are recorded in the single Family Name field so that, for example, Miguel de Cervantes Saavedra's Family Name would be recorded as 'Cervantes Saavedra.'", + "type": "string" + }, + "givenName": { + "title": "Given names", + "description": "A given name, or multiple given names, are the denominator(s) that identify an individual within a family. These are given to a person by his or her parents at birth or may be legally recognised as 'given names' through a formal process. All given names are ordered in one field so that, for example, the given name for Johann Sebastian Bach is 'Johann Sebastian'.", + "type": "string" + }, + "patronymicName": { + "title": "Patronymic Name", + "description": "Patronymic names are important in some countries. Iceland does not have a concept of family name in the way that many other European countries do, for example. In Bulgaria and Russia, patronymic names are in every day usage, for example, the 'Sergeyevich' in 'Mikhail Sergeyevich Gorbachev'.", + "type": "string" + } + } + }, + "propertyOrder": 10 + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this perrson. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to this person or entity. The scheme or list from which the identifier is drawn should be declared.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for this person or entity as provided in the declared scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme", + "description": "For entity statements, the scheme should be a entry from the org-id.guide (https://www.org-id.guide) codelist. For person statements, the scheme should have the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "string" + }, + "schemeName": { + "title": "Scheme name", + "description": "The name of this scheme, where the org-id code is unknown or only an unvalidated string is provided. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "Where this identifier has a canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) this may be included", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "nationalities": { + "title": "Nationality", + "description": "An array of ISO 2-Digit country codes representing nationalities held by this individual.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 30 + }, + "placeOfBirth": { + "title": "Place of birth", + "description": "A free text address string, providing as much address data as is relevant, suitable for processing using address parsing algorithms. For some uses (for example, Place of Birth) only a town and country are required.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "What type of address is this? See the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component of the address separated by a line-break or comma. Where postal codes are isolated fields in source systems, this `address` field SHOULD NOT include the postal code.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "The 2-letter country code (ISO 3166-1) for this address.", + "type": "string", + "minLength": 2, + "maxLength": 2 + } + }, + "propertyOrder": 40 + }, + "birthDate": { + "title": "Date of birth", + "description": "The date of birth for this individual. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$", + "propertyOrder": 35 + }, + "deathDate": { + "title": "Death date", + "description": "If this individual is no longer alive, provide their date of death. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$", + "propertyOrder": 36 + }, + "placeOfResidence": { + "title": "Place of residence", + "description": "A free text address string, providing as much address data as is relevant, suitable for processing using address parsing algorithms. For some uses (for example, Place of Birth) only a town and country are required.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "What type of address is this? See the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component of the address separated by a line-break or comma. Where postal codes are isolated fields in source systems, this `address` field SHOULD NOT include the postal code.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "The 2-letter country code (ISO 3166-1) for this address.", + "type": "string", + "minLength": 2, + "maxLength": 2 + } + }, + "propertyOrder": 50 + }, + "taxResidencies": { + "title": "Tax residency", + "description": "An array of ISO 2-Digit country codes representing the tax residencies held by this individual.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 55 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this entity.", + "type": "array", + "items": { + "title": "Address", + "description": "A free text address string, providing as much address data as is relevant, suitable for processing using address parsing algorithms. For some uses (for example, Place of Birth) only a town and country are required.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "What type of address is this? See the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component of the address separated by a line-break or comma. Where postal codes are isolated fields in source systems, this `address` field SHOULD NOT include the postal code.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "The 2-letter country code (ISO 3166-1) for this address.", + "type": "string", + "minLength": 2, + "maxLength": 2 + } + } + }, + "propertyOrder": 60 + }, + "publicationDetails": { + "title": "Publication details", + "description": "Information concerning the original publication of this statement.", + "type": "object", + "properties": { + "publicationDate": { + "title": "Publication date", + "description": "The date on which this statement was published.", + "type": "string", + "format": "date" + }, + "bodsVersion": { + "title": "BODS version", + "description": "The version of the Beneficial Ownership Data Standard to which this statement conforms, expressed as major.minor. For example: 0.2 or 1.0.", + "type": "string", + "pattern": "^(\\d+\\.)(\\d+)$" + }, + "license": { + "title": "License URL", + "description": "A link to the license that applies to this statement. The canonical URI of the license SHOULD be used. Publishers are encouraged to use a Public Domain Dedication or Open Definition Conformant (http://opendefinition.org/licenses/) license.", + "type": "string", + "format": "uri" + }, + "publisher": { + "type": "object", + "title": "Publisher", + "description": "Details of the organisation or individual publishing this statement.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the publisher", + "type": "string" + }, + "url": { + "title": "URL", + "description": "The URL of the parent dataset or of the publisher's website homepage", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "url" + ] + } + ] + } + }, + "required": [ + "publicationDate", + "bodsVersion", + "publisher" + ], + "propertyOrder": 85 + }, + "source": { + "title": "Source", + "description": "The source of information about this person, or of information that supports an unknown or anonymous person statement.", + "type": "object", + "properties": { + "type": { + "title": "Source type", + "description": "What type of source is this? Multiple tags can be combined. Values should come from the source type codelist.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Where required, additional free-text information about the source of this statement can be provided here.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "If this information was fetched from an external URL, or a machine or human readable web page is available that provides additional information on how this statement was sourced, provide the URL.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved at", + "description": "If this statement was imported from some external system, include a timestamp indicating when this took place. The statement's own date should be set based on the source information. ", + "type": "string", + "format": "date-time" + }, + "assertedBy": { + "title": "Asserted by", + "description": "Who is making this statement? This may be the name of the person or organisation making a self-declaration (in which case, please make sure the name field matches the organisation or person name field), or the name or description of some other party. If this statement has been verified, this may also include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "title": "Agent", + "description": "An individual, organisation or other responsible agent making, or supporting, a given statement or annotation.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent.", + "type": "string", + "format": "uri" + } + } + } + } + }, + "propertyOrder": 89 + }, + "annotations": { + "title": "Annotations", + "description": "Annotations about this statement or parts of this statement", + "type": "array", + "items": { + "title": "Annotation", + "description": "An annotation provides additional information about ownership or control data being provided. Annotations can be provided in free-text, and can apply to a whole statement, an object or a single field. Additional extended properties can be included on the annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this annotation applies to, starting from the root of the statement. A value of '/' indicates that the annotation applies to the whole statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date this annotation was created.", + "type": "string", + "format": "date" + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify person, organisation or agent that created this annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The motivation for this annotation, chosen from a codelist. See the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free-text description to annotate this statement or field.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed content", + "description": "A representation of the annotation target after the transformation in the description field has been applied. This field SHOULD only be used when the motivation is transformation." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "required": [ + "statementPointerTarget", + "motivation" + ], + "oneOfEnumSelectorField": "motivation", + "oneOf": [ + { + "properties": { + "motivation": { + "enum": [ + "linking" + ] + } + }, + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + { + "properties": { + "motivation": { + "enum": [ + "identifying", + "commenting", + "correcting", + "transformation" + ] + } + } + } + ] + }, + "propertyOrder": 90 + }, + "replacesStatements": { + "title": "Replaces statement(s)", + "description": "If this statement replaces a previous statement or statements, provide the identifier(s) for the previous statement(s) here. Consuming applications are advised to mark the identified statements as no longer active.", + "type": "array", + "items": { + "title": "Statement identifier", + "description": "The identifier of a statement that is no longer active.", + "type": "string", + "minLength": 32, + "maxLength": 64 + } + }, + "politicalExposure": { + "type": "object", + "title": "Political exposure", + "description": "Information about whether, and how, the person described by this statement is politically exposed. Use this property only if politically exposed person (PEP) declarations are expected as part of beneficial ownership declarations.", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "title": "Politically exposed person (PEP) status", + "description": "This value is 'isPep' or 'isNotPep' according to whether the person described by this statement has the status of politically exposed person (PEP). An 'unknown' value means a PEP status declaration is expected but missing; the reason for the missing data SHOULD be supplied in the details array.", + "enum": [ + "isPep", + "isNotPep", + "unknown" + ] + }, + "details": { + "type": "array", + "title": "Politically exposed person (PEP) details", + "description": "One or more descriptions of this person's Politically Exposed Person (PEP) status.", + "items": { + "title": "PEP Status", + "description": "A description of a politically-exposed person status.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason for this person being declared a politically-exposed person.", + "type": "string" + }, + "missingInfoReason": { + "title": "Missing information reason(s)", + "description": "An explanation of the reason that PEP status for the person is not provided (i.e. `politicalExposure.status` is 'unknown'). This may be a standard descriptive phrase from the source system, or a free-text justification. Where this field is present it should be the only field except for `source`.", + "type": "string" + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "The jurisdiction where this person is a PEP.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or subdivision code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "startDate": { + "title": "State date", + "description": "When did this PEP status begin. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$" + }, + "endDate": { + "title": "End date", + "description": "When did this PEP status end. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$" + }, + "source": { + "title": "Source", + "description": "The source of this PEP information", + "type": "object", + "properties": { + "type": { + "title": "Source type", + "description": "What type of source is this? Multiple tags can be combined. Values should come from the source type codelist.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Where required, additional free-text information about the source of this statement can be provided here.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "If this information was fetched from an external URL, or a machine or human readable web page is available that provides additional information on how this statement was sourced, provide the URL.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved at", + "description": "If this statement was imported from some external system, include a timestamp indicating when this took place. The statement's own date should be set based on the source information. ", + "type": "string", + "format": "date-time" + }, + "assertedBy": { + "title": "Asserted by", + "description": "Who is making this statement? This may be the name of the person or organisation making a self-declaration (in which case, please make sure the name field matches the organisation or person name field), or the name or description of some other party. If this statement has been verified, this may also include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "title": "Agent", + "description": "An individual, organisation or other responsible agent making, or supporting, a given statement or annotation.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent.", + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + } + } + }, + "required": [ + "statementID", + "statementType", + "personType", + "isComponent", + "publicationDetails" + ] + }, + { + "id": "ownership-or-control-statement.json", + "$schema": "http://json-schema.org/draft-04/schema#", + "version": "0.3", + "title": "Ownership or control Statement", + "description": "An ownership or control statement is made up of an entity, an interested party (a reference to an entity, natural person, arrangement or trust), details of the interest and provenance information for the statement.", + "type": "object", + "properties": { + "statementID": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this statement.", + "type": "string", + "minLength": 32, + "maxLength": 64 + }, + "statementType": { + "title": "Statement type", + "description": "This MUST be 'ownershipOrControlStatement'.", + "type": "string", + "enum": [ + "ownershipOrControlStatement" + ] + }, + "statementDate": { + "title": "Statement date", + "description": "The date on which this statement was made.", + "type": "string", + "format": "date" + }, + "isComponent": { + "title": "Is component", + "description": "Does this Ownership-or-control Statement represent a component of a wider indirect ownership-or-control relationship? Where `isComponent` is 'true': (1) the `statementID` of this secondary Ownership-or-control Statement MUST be an element in the `componentStatementIDs` array of that primary Ownership-or-control Statement, (2) this Ownership-or-control Statement MUST come before that primary Ownership-or-control Statement in a BODS package or stream, (3) the replacement of this Ownership-or-control Statement SHOULD be considered when replacing the primary Ownership-or-control Statement, and (4) the primary Ownership-or-control Statement MUST have a `isComponent` value of 'false'. Where `isComponent` is 'false', this Ownership-or-control Statement is the primary declaration of the relationship between the `subject` and the `interestedParty`.", + "type": "boolean" + }, + "componentStatementIDs": { + "title": "Component statement IDs", + "description": "The identifiers of all component statements that provide detail about the indirect relationship between this Statement's `subject` and `interestedParty`. If this Ownership-or-control Statement has components, it MUST itself have a `isComponent` value of 'false'.", + "type": "array", + "items": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this statement.", + "type": "string", + "minLength": 32, + "maxLength": 64 + } + }, + "subject": { + "title": "Subject", + "description": "The subject of an ownership or control relationship.", + "type": "object", + "properties": { + "describedByEntityStatement": { + "title": "Described by entity statement", + "description": "Provide the identifier of the statement which describes the entity that the subject of an ownership or control interest.", + "type": "string" + } + }, + "required": [ + "describedByEntityStatement" + ] + }, + "interestedParty": { + "title": "Interested party", + "description": "The interested party has some level of ownership or control over the entity referenced in this ownership or control statement. This should be described with reference to either an entity statement or person statement, or, where the interested party is unknown, details of why. ", + "type": "object", + "properties": { + "describedByEntityStatement": { + "title": "Described by entity statement", + "description": "A reference to a statement describing a registered entity, trust or arrangement that has an ownership or control interest in the subject of this statement. An entityStatement should be used when the direct interests to be described represents known control or ownership by anyone other than a natural person.", + "type": "string" + }, + "describedByPersonStatement": { + "title": "Described by person statement", + "description": "A reference to a statement describing a natural person who has an ownership or control interest in the subject of this statement.", + "type": "string" + }, + "unspecified": { + "title": "Unspecified or unknown ownership and control", + "description": "When confirmation has been provided that no interested party exists, where ownership and control information does not need to be provided, or where details of ownership and control are unknown, a `reason` MUST be given. Where an unknown entity is the `subject` of further ownershipOrControlStatements in the same structure, or where there is a natural person with ownership or control but their name or details are not known or cannot be disclosed for some reason, `unspecified` should not be used, but instead a reference to a `personStatement` or `entityStatement` should be provided but identifying details MAY be left blank.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that an interested party cannot be specified. From the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Any supporting information about the absence of a confirmed beneficial owner. This field may be used to provide set phrases from a source system, or for a free-text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + } + }, + "interests": { + "title": "Interests", + "description": "A description of the interests held by the interestedParty covered by this statement in the entity covered by this statement.", + "type": "array", + "items": { + "title": "Interest", + "description": "A description of the interest held by an interestedParty in another entity.", + "type": "object", + "properties": { + "type": { + "title": "Type of interest", + "description": "A codelist value indicating the nature of the interest. See the interestType codelist", + "type": "string", + "enum": [ + "shareholding", + "votingRights", + "appointmentOfBoard", + "otherInfluenceOrControl", + "seniorManagingOfficial", + "settlor", + "trustee", + "protector", + "beneficiaryOfLegalArrangement", + "rightsToSurplusAssetsOnDissolution", + "rightsToProfitOrIncome", + "rightsGrantedByContract", + "conditionalRightsGrantedByContract", + "controlViaCompanyRulesOrArticles", + "controlByLegalFramework", + "boardMember", + "boardChair", + "unknownInterest", + "unpublishedInterest", + "enjoymentAndUseOfAssets", + "rightToProfitOrIncomeFromAssets" + ], + "codelist": "interestType.csv", + "openCodelist": false + }, + "directOrIndirect": { + "title": "Direct or indirect", + "description": "How directly the interest is exercised by the interested party. The value MUST be 'indirect' if intermediate entities or agents are known to exist, and MUST be 'direct' if such intermediaries are known not to exist. Otherwise the value MUST be 'unknown'.", + "type": "string", + "enum": [ + "direct", + "indirect", + "unknown" + ], + "codelist": "directOrIndirect.csv", + "openCodelist": false + }, + "beneficialOwnershipOrControl": { + "title": "Beneficial ownership or control", + "description": "Does this statement assert this as a beneficial ownership or control interest? A beneficial ownership or control interest is always between a natural person and some entity, and exists where the person ultimately benefits from, or has a degree of control over, the entity. There may be cases where a person has an interest in an entity, but where there are arrangements or other conditions that mean this interest does not constitute beneficial ownership or control.", + "type": "boolean" + }, + "details": { + "title": "Details", + "description": "This field may be used to provide the local name given to this kind of interest, or any further semi-structured or unstructured information to clarify the nature of the interest held.", + "type": "string" + }, + "share": { + "title": "Percentage share", + "description": "Where an exact percentage is available, this should be given, and `maximum` and `minimum` values set to the same as the exact percentage. Otherwise, `maximum` and `minimum` can be used to record the range into which the share of this kind of interest falls. By default the `minimum` is inclusive and the `maximum` exclusive (minimum-value \u2264 share < maximum-value). If you wish to change these defaults, use the `exclusiveMinimum` and `exclusiveMaximum` properties.", + "type": "object", + "properties": { + "exact": { + "title": "Exact share", + "description": "The exact share of this interest held (where available).", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "maximum": { + "title": "Maximum share", + "description": "The upper bound of the share of this interest known to be held.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "minimum": { + "title": "Minimum share", + "description": "The lower bound of the share of this interest known to be held.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMinimum": { + "title": "Exclusive minimum", + "description": "If `exclusiveMinimum` is true, then the share is at least greater than the `minimum` value given. E.g. if `minimum` is '25', the share is at least 25.1, and not simply 25.", + "type": "boolean", + "default": false + }, + "exclusiveMaximum": { + "title": "Exclusive maximum", + "description": "If `exclusiveMaximum` is true, then the share is at least less than the `maximum` value given. E.g. if `maximum` is '50', the share is less than 49.999, and not simply 50.", + "type": "boolean", + "default": true + } + } + }, + "startDate": { + "title": "Start date", + "description": "When did this interest first occur. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$" + }, + "endDate": { + "title": "End date", + "description": "When did this interest cease. Please provide as precise a date as possible in ISO 8601 format. When only the year or year and month is known, these can be given as YYYY or YYYY-MM.", + "type": "string", + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$" + } + } + } + }, + "publicationDetails": { + "title": "Publication details", + "description": "Information concerning the original publication of this statement.", + "type": "object", + "properties": { + "publicationDate": { + "title": "Publication date", + "description": "The date on which this statement was published.", + "type": "string", + "format": "date" + }, + "bodsVersion": { + "title": "BODS version", + "description": "The version of the Beneficial Ownership Data Standard to which this statement conforms, expressed as major.minor. For example: 0.2 or 1.0.", + "type": "string", + "pattern": "^(\\d+\\.)(\\d+)$" + }, + "license": { + "title": "License URL", + "description": "A link to the license that applies to this statement. The canonical URI of the license SHOULD be used. Publishers are encouraged to use a Public Domain Dedication or Open Definition Conformant (http://opendefinition.org/licenses/) license.", + "type": "string", + "format": "uri" + }, + "publisher": { + "type": "object", + "title": "Publisher", + "description": "Details of the organisation or individual publishing this statement.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the publisher", + "type": "string" + }, + "url": { + "title": "URL", + "description": "The URL of the parent dataset or of the publisher's website homepage", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "url" + ] + } + ] + } + }, + "required": [ + "publicationDate", + "bodsVersion", + "publisher" + ] + }, + "source": { + "title": "Source", + "description": "The source of the information that links the entity and the interested party, or that supports a null statement.", + "type": "object", + "properties": { + "type": { + "title": "Source type", + "description": "What type of source is this? Multiple tags can be combined. Values should come from the source type codelist.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Where required, additional free-text information about the source of this statement can be provided here.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "If this information was fetched from an external URL, or a machine or human readable web page is available that provides additional information on how this statement was sourced, provide the URL.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved at", + "description": "If this statement was imported from some external system, include a timestamp indicating when this took place. The statement's own date should be set based on the source information. ", + "type": "string", + "format": "date-time" + }, + "assertedBy": { + "title": "Asserted by", + "description": "Who is making this statement? This may be the name of the person or organisation making a self-declaration (in which case, please make sure the name field matches the organisation or person name field), or the name or description of some other party. If this statement has been verified, this may also include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "title": "Agent", + "description": "An individual, organisation or other responsible agent making, or supporting, a given statement or annotation.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent.", + "type": "string", + "format": "uri" + } + } + } + } + } + }, + "annotations": { + "title": "Annotations", + "description": "Annotations about this statement or parts of this statement", + "type": "array", + "items": { + "title": "Annotation", + "description": "An annotation provides additional information about ownership or control data being provided. Annotations can be provided in free-text, and can apply to a whole statement, an object or a single field. Additional extended properties can be included on the annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this annotation applies to, starting from the root of the statement. A value of '/' indicates that the annotation applies to the whole statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date this annotation was created.", + "type": "string", + "format": "date" + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify person, organisation or agent that created this annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The motivation for this annotation, chosen from a codelist. See the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free-text description to annotate this statement or field.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed content", + "description": "A representation of the annotation target after the transformation in the description field has been applied. This field SHOULD only be used when the motivation is transformation." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "required": [ + "statementPointerTarget", + "motivation" + ], + "oneOfEnumSelectorField": "motivation", + "oneOf": [ + { + "properties": { + "motivation": { + "enum": [ + "linking" + ] + } + }, + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + { + "properties": { + "motivation": { + "enum": [ + "identifying", + "commenting", + "correcting", + "transformation" + ] + } + } + } + ] + } + }, + "replacesStatements": { + "title": "Replaces statement(s)", + "description": "If this statement replaces a previous statement or statements, provide the identifier(s) for the previous statement(s) here. Consuming applications are advised to mark the identified statements as no longer active.", + "type": "array", + "items": { + "title": "Statement identifier", + "description": "The identifier of a statement that is no longer active.", + "type": "string", + "minLength": 32, + "maxLength": 64 + } + } + }, + "required": [ + "statementID", + "statementType", + "isComponent", + "subject", + "interestedParty", + "publicationDetails" + ], + "definitions": { + "InterestedParty": { + "title": "Interested party", + "description": "The interested party has some level of ownership or control over the entity referenced in this ownership or control statement. This should be described with reference to either an entity statement or person statement, or, where the interested party is unknown, details of why. ", + "type": "object", + "properties": { + "describedByEntityStatement": { + "title": "Described by entity statement", + "description": "A reference to a statement describing a registered entity, trust or arrangement that has an ownership or control interest in the subject of this statement. An entityStatement should be used when the direct interests to be described represents known control or ownership by anyone other than a natural person.", + "type": "string" + }, + "describedByPersonStatement": { + "title": "Described by person statement", + "description": "A reference to a statement describing a natural person who has an ownership or control interest in the subject of this statement.", + "type": "string" + }, + "unspecified": { + "title": "Unspecified or unknown ownership and control", + "description": "When confirmation has been provided that no interested party exists, where ownership and control information does not need to be provided, or where details of ownership and control are unknown, a `reason` MUST be given. Where an unknown entity is the `subject` of further ownershipOrControlStatements in the same structure, or where there is a natural person with ownership or control but their name or details are not known or cannot be disclosed for some reason, `unspecified` should not be used, but instead a reference to a `personStatement` or `entityStatement` should be provided but identifying details MAY be left blank.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that an interested party cannot be specified. From the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Any supporting information about the absence of a confirmed beneficial owner. This field may be used to provide set phrases from a source system, or for a free-text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + } + } + } + } + ] + } +} diff --git a/tests/fixtures/schema-0-4-0.json b/tests/fixtures/schema-0-4-0.json new file mode 100644 index 0000000..98a88a9 --- /dev/null +++ b/tests/fixtures/schema-0-4-0.json @@ -0,0 +1,4219 @@ +{ + "$id": "urn:statement", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Statements", + "description": "An array of Statements.", + "version": "0.4", + "type": "array", + "items": { + "title": "Statement", + "description": "A claim about a person, entity or relationship, made at a particular point in time.", + "type": "object", + "properties": { + "statementId": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this Statement. Length MUST be 32 - 64 characters (inclusive).", + "type": "string", + "minLength": 32, + "maxLength": 64 + }, + "statementDate": { + "title": "Statement Date", + "description": "The date on which this statement was declared by the source, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "annotations": { + "title": "Annotations", + "description": "Annotations about this Statement or parts of this Statement", + "type": "array", + "items": { + "title": "Annotation", + "description": "Additional information about the data contained in this Statement. Annotations can apply to a whole statement, an object or a single field. Custom properties can be included within the Annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this Annotation applies to, starting from the root of the Statement. An empty string (\"\") indicates that the Annotation applies to the whole Statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date on which this Annotation was created, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this Annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this Annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the person, organisation or agent that created this Annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The reason for this Annotation, using the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free text description providing extra information about part of this Statement.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed Content", + "description": "A representation of the Annotation target after the transformation in the `description` field has been applied. This field MUST only be used when the `motivation` is 'transformation'." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this Statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "allOf": [ + { + "if": { + "properties": { + "motivation": { + "const": "linking" + } + } + }, + "then": { + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + "else": { + "required": [ + "statementPointerTarget", + "motivation" + ] + } + }, + { + "if": { + "not": { + "properties": { + "motivation": { + "const": "transformation" + } + } + } + }, + "then": { + "properties": { + "transformedContent": { + "const": "" + } + } + } + } + ] + } + }, + "publicationDetails": { + "title": "Publication Details", + "description": "Information concerning the publication of this Statement.", + "type": "object", + "properties": { + "publicationDate": { + "title": "Publication date", + "description": "The date on which this statement was published, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "bodsVersion": { + "title": "BODS Version", + "description": "The version of the Beneficial Ownership Data Standard to which this Statement conforms, expressed as major.minor (e.g. 0.2 or 1.0). In a published BODS dataset, all Statements MUST have the same major version number.", + "type": "string", + "pattern": "^(\\d+\\.)(\\d+)$" + }, + "license": { + "title": "License URL", + "description": "A link to the license that applies to this Statement. The canonical URI of the license SHOULD be used. Publishers are encouraged to use a Public Domain Dedication or Open Definition Conformant (http://opendefinition.org/licenses/) license.", + "type": "string", + "format": "uri" + }, + "publisher": { + "type": "object", + "title": "Publisher", + "description": "Details of the organisation or person publishing a Statement.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the publisher.", + "type": "string" + }, + "url": { + "title": "URL", + "description": "The URL where details of the full dataset, or of the publisher, can be found.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "url" + ] + } + ] + } + }, + "required": [ + "publicationDate", + "bodsVersion", + "publisher" + ] + }, + "source": { + "title": "Source", + "description": "The source of information in this statement. Each statement SHOULD contain source information.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + }, + "declaration": { + "title": "Declaration Reference", + "description": "An identifier or reference for a declaration within the publisher\u2019s system. Where a Statement is a claim from a particular declaration (made at a point in time by a `source` about a `declarationSubject`) this field identifies the declaration.", + "type": "string" + }, + "declarationSubject": { + "title": "Declaration Subject", + "description": "A `recordId` value for the subject of a beneficial ownership network (always an entity or person).", + "type": "string" + }, + "recordId": { + "title": "Record Identifier", + "description": "A unique identifier for the record (within the publisher's system) to which this Statement relates. (A record captures information about an entity, natural person or relationship within the beneficial ownership network of a particular declaration subject.)", + "type": "string" + }, + "recordType": { + "title": "Record Type", + "description": "The type of record (within the publisher's system) to which this Statement relates: entity, person, or relationship.", + "type": "string", + "enum": [ + "person", + "entity", + "relationship" + ], + "codelist": "recordType.csv", + "openCodelist": false + }, + "recordStatus": { + "title": "Record Status", + "description": "The lifecycle status of the record (within the publisher's system) to which this Statement relates, using the recordStatus codelist.", + "type": "string", + "enum": [ + "new", + "updated", + "closed" + ], + "codelist": "recordStatus.csv", + "openCodelist": false + }, + "recordDetails": { + "title": "Record Details", + "description": "The details of the entity, person or relationship as declared on the Statement Date.", + "type": "object" + } + }, + "allOf": [ + { + "if": { + "properties": { + "recordType": { + "const": "entity" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:entity", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "title": "Entity Record Details", + "description": "Information about an entity.", + "type": "object", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this entity is a component in an indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this entity MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Entity Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Entity Statement SHOULD be considered when replacing the primary Relationship Statement. The primary Relationship statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "entityType": { + "type": "object", + "title": "Entity Type", + "description": "The form of the entity described in the Statement.", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "title": "Type", + "description": "The general form of the entity, using the entityType codelist.", + "codelist": "entityType.csv", + "enum": [ + "registeredEntity", + "legalEntity", + "arrangement", + "anonymousEntity", + "unknownEntity", + "state", + "stateBody" + ] + }, + "subtype": { + "type": "string", + "title": "Subtype", + "description": "The particular form of the entity, where relevant, using the entitySubtype codelist. The value MUST align with the `entityType` value.", + "codelist": "entitySubtype.csv", + "enum": [ + "governmentDepartment", + "stateAgency", + "other", + "trust", + "nomination" + ], + "openCodelist": false + }, + "details": { + "type": "string", + "title": "Details", + "description": "This may be used to provide a local name for this type of entity, or any further information to identify the type of entity. For example, in Finland 'ministeri\u00f6' for a government department." + } + }, + "propertyOrder": 4, + "allOf": [ + { + "if": { + "properties": { + "type": { + "enum": [ + "arrangement" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "trust", + "nomination", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "legalEntity" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "trust", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "stateBody" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "governmentDepartment", + "stateAgency", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "registeredEntity", + "state", + "anonymousEntity", + "unknownEntity" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "other" + ] + } + } + } + } + ] + }, + "unspecifiedEntityDetails": { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + }, + "name": { + "title": "Entity Name", + "description": "The declared name of this entity.", + "type": "string", + "propertyOrder": 10 + }, + "alternateNames": { + "title": "Alternative Names", + "description": "An array of other names this entity is known by.", + "type": "array", + "items": { + "type": "string", + "title": "Name", + "description": "A name this entity is known by." + }, + "propertyOrder": 12 + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this entity. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to a person or entity. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for a person or entity, as issued by the scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme Code", + "description": "For entities, a code from org-id.guide (https://www.org-id.guide) for an identifier-issuing authority (e.g. 'GB-COH'). For natural persons, a value with the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3166-1 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD.", + "type": "string" + }, + "schemeName": { + "title": "Scheme Name", + "description": "The name of the identifier-issuing authority.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "A canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) for the identifier and associated details of the person or entity, if one exists.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "foundingDate": { + "title": "Founding Date", + "description": "The date on which this entity was founded, created or registered. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date", + "propertyOrder": 30 + }, + "dissolutionDate": { + "title": "Dissolution Date", + "description": "The date on which this entity was dissolved or ceased, if it is no longer active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date", + "propertyOrder": 35 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this entity.", + "type": "array", + "items": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "propertyOrder": 40 + }, + "uri": { + "title": "URI", + "description": "Where a persistent URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) is available for this entity this should be included.", + "type": "string", + "format": "uri", + "propertyOrder": 21 + }, + "publicListing": { + "type": "object", + "title": "Public Listing", + "description": "Details of a publicly listed company, its securities (shares and other tradable financial instruments related to the entity), and related regulatory filings.", + "required": [ + "hasPublicListing" + ], + "minProperties": 1, + "properties": { + "hasPublicListing": { + "type": "boolean", + "title": "Has Public Listing", + "description": "Whether the entity is a publicly listed company." + }, + "companyFilingsURLs": { + "type": "array", + "title": "Company Filings URLs", + "description": "URL or URLs where regulatory filings related to major holdings can be retrieved. URLs may point to pages maintained by regulatory bodies, stock exchanges or by the company itself.", + "items": { + "type": "string", + "format": "uri" + } + }, + "securitiesListings": { + "type": "array", + "title": "Securities Listings", + "description": "Details of the entity's securities and the public exchanges and markets on which they are traded. All equity securities SHOULD be listed here, plus any other securities from which beneficial ownership might be derived. Where a security is traded on more than one market, there SHOULD be an entry for each market (or market segment).", + "items": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + }, + "formedByStatute": { + "type": "object", + "title": "Formed by Statute", + "description": "The law which mandated the formation of the entity described in the statement, where applicable. This information SHOULD be provided where a state has created an agency or other entity with specific legislation.", + "properties": { + "name": { + "type": "string", + "title": "Statute Name", + "description": "The name of the law. " + }, + "date": { + "type": "string", + "title": "Date", + "description": "The date on which the law came into force. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "format": "date" + } + }, + "propertyOrder": 18 + } + }, + "required": [ + "isComponent", + "entityType" + ], + "$defs": { + "PublicListing": { + "type": "object", + "title": "Public Listing", + "description": "Details of a publicly listed company, its securities (shares and other tradable financial instruments related to the entity), and related regulatory filings.", + "required": [ + "hasPublicListing" + ], + "minProperties": 1, + "properties": { + "hasPublicListing": { + "type": "boolean", + "title": "Has Public Listing", + "description": "Whether the entity is a publicly listed company." + }, + "companyFilingsURLs": { + "type": "array", + "title": "Company Filings URLs", + "description": "URL or URLs where regulatory filings related to major holdings can be retrieved. URLs may point to pages maintained by regulatory bodies, stock exchanges or by the company itself.", + "items": { + "type": "string", + "format": "uri" + } + }, + "securitiesListings": { + "type": "array", + "title": "Securities Listings", + "description": "Details of the entity's securities and the public exchanges and markets on which they are traded. All equity securities SHOULD be listed here, plus any other securities from which beneficial ownership might be derived. Where a security is traded on more than one market, there SHOULD be an entry for each market (or market segment).", + "items": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + }, + "SecuritiesListing": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + } + } + }, + { + "if": { + "properties": { + "recordType": { + "const": "person" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:person", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "type": "object", + "title": "Person Record Details", + "description": "Information about a natural person.", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this person is a component of an indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this person MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Person Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Person Statement SHOULD be considered when replacing the primary Relationship Statement. The primary Relationship Statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "personType": { + "title": "Person Type", + "description": "The status of this person, using the personType codelist. Where a person has the type 'anonymousPerson' or 'unknownPerson' a reason for the absence of information SHOULD be provided in 'unspecifiedPersonDetails'", + "type": "string", + "enum": [ + "anonymousPerson", + "unknownPerson", + "knownPerson" + ], + "propertyOrder": 4, + "codelist": "personType.csv", + "openCodelist": false + }, + "unspecifiedPersonDetails": { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + }, + "names": { + "title": "Names", + "description": "One or more known names for this person.", + "type": "array", + "items": { + "title": "Name", + "description": "A name by which this person is known. A name MUST be provided in `fullName`, and MAY be broken down in the `familyName`, `givenName` and `patronymicName` fields, based on the EC ISA Core Person Vocabulary (https://joinup.ec.europa.eu/solution/e-government-core-vocabularies) definitions.", + "type": "object", + "required": [ + "fullName" + ], + "properties": { + "type": { + "title": "Type", + "description": "The status of this name for the person, using the nameType codelist.", + "type": "string", + "enum": [ + "legal", + "translation", + "transliteration", + "former", + "alternative", + "birth" + ], + "codelist": "nameType.csv", + "openCodelist": false + }, + "fullName": { + "title": "Full Name", + "description": "The complete name of the person.", + "type": "string" + }, + "familyName": { + "title": "Family Name", + "description": "Part of the person's `fullName` which is shared by family members. The value may include prefixes or suffixes, e.g. 'de Boer', 'van de Putte', 'von und zu Orlow'. The value may be a multiple-part family name, such as are commonly found in Hispanic countries. For example, Miguel de Cervantes Saavedra's Family Name would be recorded as 'de Cervantes Saavedra.'", + "type": "string" + }, + "givenName": { + "title": "Given Names", + "description": "The part of the person's `fullName` that identifies the person within their family. These are given to a person by their parents at birth or may be legally recognised as 'given names' through a formal process. For example, the given name for Johann Sebastian Bach is 'Johann Sebastian'.", + "type": "string" + }, + "patronymicName": { + "title": "Patronymic Name", + "description": "Part of the person's `fullName` which is inherited from their father, as is common in countries such as Iceland, Ethiopia and Russia. For example, the 'Sergeyevich' in 'Mikhail Sergeyevich Gorbachev'.", + "type": "string" + } + } + }, + "propertyOrder": 10 + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this person. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to a person or entity. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for a person or entity, as issued by the scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme Code", + "description": "For entities, a code from org-id.guide (https://www.org-id.guide) for an identifier-issuing authority (e.g. 'GB-COH'). For natural persons, a value with the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3166-1 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD.", + "type": "string" + }, + "schemeName": { + "title": "Scheme Name", + "description": "The name of the identifier-issuing authority.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "A canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) for the identifier and associated details of the person or entity, if one exists.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "nationalities": { + "title": "Nationality", + "description": "The nationalities held by this person.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 30 + }, + "placeOfBirth": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "birthDate": { + "title": "Date of Birth", + "description": "The date of birth for this person, in YYYY, YYYY-MM, or YYYY-MM-DD format.", + "type": "string", + "anyOf": [ + { + "pattern": "^(\\d{4})(-(1[0-2]|0[1-9]))?$" + }, + { + "format": "date" + } + ], + "propertyOrder": 35 + }, + "deathDate": { + "title": "Death Date", + "description": "The date of death for this person, in YYYY, YYYY-MM, or YYYY-MM-DD format.", + "type": "string", + "anyOf": [ + { + "pattern": "^(\\d{4})(-(1[0-2]|0[1-9]))?$" + }, + { + "format": "date" + } + ], + "propertyOrder": 36 + }, + "taxResidencies": { + "title": "Tax Residency", + "description": "The tax residencies held by this person, as an array of Country objects.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 55 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this person.", + "type": "array", + "items": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "propertyOrder": 60 + }, + "politicalExposure": { + "type": "object", + "title": "Political Exposure", + "description": "Information about whether, and how, the person described by this statement is politically exposed. Use this property only if politically exposed person (PEP) declarations are expected as part of beneficial ownership declarations.", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "title": "Politically Exposed Person (PEP) Status", + "description": "This value is 'isPep' or 'isNotPep' according to whether the person described by this statement has the status of politically exposed person (PEP). An 'unknown' value means a PEP status declaration is expected but missing; the reason for the missing data SHOULD be supplied in the `details` array.", + "enum": [ + "isPep", + "isNotPep", + "unknown" + ] + }, + "details": { + "type": "array", + "title": "Politically Exposed Person (PEP) Details", + "description": "One or more descriptions of this person's Politically Exposed Person (PEP) status.", + "items": { + "title": "PEP Status Details", + "description": "Information about a person's political involvement.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason for this person being declared a politically-exposed person.", + "type": "string" + }, + "missingInfoReason": { + "title": "Missing Information Reasons", + "description": "An explanation of why the PEP status for the person is not provided (i.e. `politicalExposure.status` is 'unknown'). This may be a standard descriptive phrase from the source system, or a free text justification. Where this field is present it should be the only field except for `source`.", + "type": "string" + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "startDate": { + "title": "State Date", + "description": "The date from which this person had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this person no longer had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "source": { + "title": "Source", + "description": "Details describing an information source.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + } + } + }, + "required": [ + "personType", + "isComponent" + ], + "$defs": { + "Name": { + "title": "Name", + "description": "A name by which this person is known. A name MUST be provided in `fullName`, and MAY be broken down in the `familyName`, `givenName` and `patronymicName` fields, based on the EC ISA Core Person Vocabulary (https://joinup.ec.europa.eu/solution/e-government-core-vocabularies) definitions.", + "type": "object", + "required": [ + "fullName" + ], + "properties": { + "type": { + "title": "Type", + "description": "The status of this name for the person, using the nameType codelist.", + "type": "string", + "enum": [ + "legal", + "translation", + "transliteration", + "former", + "alternative", + "birth" + ], + "codelist": "nameType.csv", + "openCodelist": false + }, + "fullName": { + "title": "Full Name", + "description": "The complete name of the person.", + "type": "string" + }, + "familyName": { + "title": "Family Name", + "description": "Part of the person's `fullName` which is shared by family members. The value may include prefixes or suffixes, e.g. 'de Boer', 'van de Putte', 'von und zu Orlow'. The value may be a multiple-part family name, such as are commonly found in Hispanic countries. For example, Miguel de Cervantes Saavedra's Family Name would be recorded as 'de Cervantes Saavedra.'", + "type": "string" + }, + "givenName": { + "title": "Given Names", + "description": "The part of the person's `fullName` that identifies the person within their family. These are given to a person by their parents at birth or may be legally recognised as 'given names' through a formal process. For example, the given name for Johann Sebastian Bach is 'Johann Sebastian'.", + "type": "string" + }, + "patronymicName": { + "title": "Patronymic Name", + "description": "Part of the person's `fullName` which is inherited from their father, as is common in countries such as Iceland, Ethiopia and Russia. For example, the 'Sergeyevich' in 'Mikhail Sergeyevich Gorbachev'.", + "type": "string" + } + } + }, + "PepStatusDetails": { + "title": "PEP Status Details", + "description": "Information about a person's political involvement.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason for this person being declared a politically-exposed person.", + "type": "string" + }, + "missingInfoReason": { + "title": "Missing Information Reasons", + "description": "An explanation of why the PEP status for the person is not provided (i.e. `politicalExposure.status` is 'unknown'). This may be a standard descriptive phrase from the source system, or a free text justification. Where this field is present it should be the only field except for `source`.", + "type": "string" + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "startDate": { + "title": "State Date", + "description": "The date from which this person had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this person no longer had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "source": { + "title": "Source", + "description": "Details describing an information source.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + } + } + } + }, + { + "if": { + "properties": { + "recordType": { + "const": "relationship" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:relationship", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "title": "Relationship Record Details", + "description": "Information about the interests that an interested party (a person or entity) holds in the subject (an entity).", + "type": "object", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this relationship is a component of a wider indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this secondary Relationship Statement MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Relationship Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Relationship Statement SHOULD be considered when replacing the primary Relationship Statement, and (4) the primary Relationship Statement MUST have an `isComponent` value of 'false'. Where `isComponent` is 'false', this Relationship Statement is the primary declaration of the relationship between the `subject` and the `interestedParty`.", + "type": "boolean" + }, + "componentRecords": { + "title": "Component Record IDs", + "description": "The `recordId` values of all component records that provide detail about this relationship between the `subject` and the `interestedParty` (if it is indirect). If this relationship has components, its own `isComponent` value MUST be 'false'.", + "type": "array", + "items": { + "type": "string" + } + }, + "subject": { + "title": "Subject", + "description": "The `recordId` for the subject of the relationship, or a reason why the subject cannot be specified. The subject MUST be an entity.", + "oneOf": [ + { + "type": "string" + }, + { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + ] + }, + "interestedParty": { + "title": "Interested Party", + "description": "The `recordId` for the interested party in the relationship, or an Unspecified Record object with a reason for why this information has not been disclosed. The interested party MAY be an entity or a person. An Unspecified Record SHOULD only be used where no information at all is known about interested parties beyond this point of the beneficial ownership network. If the interested party is known to be an entity or person but their particular identity is unavailable, a `recordId` for them SHOULD be provided here (and the their `recordDetails.[person|entity]Type` should indicate that they are anonymous or unknown).", + "oneOf": [ + { + "type": "string" + }, + { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + ] + }, + "interests": { + "title": "Interests", + "description": "A description of the interests held by the interested party in the subject.", + "type": "array", + "items": { + "title": "Interest", + "description": "A description of an interest held by an interestedParty in the subject.", + "type": "object", + "properties": { + "type": { + "title": "Type of Interest", + "description": "The nature of the interest, using the interestType codelist.", + "type": "string", + "enum": [ + "shareholding", + "votingRights", + "appointmentOfBoard", + "otherInfluenceOrControl", + "seniorManagingOfficial", + "settlor", + "trustee", + "protector", + "beneficiaryOfLegalArrangement", + "rightsToSurplusAssetsOnDissolution", + "rightsToProfitOrIncome", + "rightsGrantedByContract", + "conditionalRightsGrantedByContract", + "controlViaCompanyRulesOrArticles", + "controlByLegalFramework", + "boardMember", + "boardChair", + "unknownInterest", + "unpublishedInterest", + "enjoymentAndUseOfAssets", + "rightToProfitOrIncomeFromAssets", + "nominee", + "nominator" + ], + "codelist": "interestType.csv", + "openCodelist": false + }, + "directOrIndirect": { + "title": "Direct or Indirect", + "description": "How directly the interest is exercised by the interested party. The value MUST be 'indirect' if intermediate entities or agents are known to exist, and MUST be 'direct' if such intermediaries are known not to exist. Otherwise the value MUST be 'unknown'.", + "type": "string", + "enum": [ + "direct", + "indirect", + "unknown" + ], + "codelist": "directOrIndirect.csv", + "openCodelist": false + }, + "beneficialOwnershipOrControl": { + "title": "Beneficial Ownership or Control", + "description": "Whether this interest (alone or with others) means the interested party is a beneficial owner of the subject. If 'true' the interested party MUST be a natural person. The definition of 'beneficial owner' in operation SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "boolean" + }, + "details": { + "title": "Details", + "description": "The local name given to this kind of interest, or further information (semi-structured or unstructured) to clarify the nature of the interest.", + "type": "string" + }, + "share": { + "title": "Percentage Share", + "description": "The proportion of this type of interest held by the interested party, where an interest is countable. Provide the `exact` percentage if known. Otherwise, `minimum` (or `exclusiveMinimum`) and `maximum` (or `exclusiveMaximum`) can be used to record the range into which the proportion falls. (The `minimum` and `maximum` values are inclusive.)", + "type": "object", + "properties": { + "exact": { + "title": "Exact percentage", + "description": "The exact share of this interest held (if available).", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "maximum": { + "title": "Maximum Percentage", + "description": "The inclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "minimum": { + "title": "Minimum Percentage", + "description": "The inclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMinimum": { + "title": "Exclusive Minimum percentage", + "description": "The exclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMaximum": { + "title": "Exclusive Maximum Percentage", + "description": "The exclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + } + } + }, + "startDate": { + "title": "Start Date", + "description": "The date from which this interest was active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this interest ceased to exist. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + } + } + } + } + }, + "required": [ + "isComponent", + "subject", + "interestedParty" + ], + "if": { + "properties": { + "isComponent": { + "const": true + } + } + }, + "then": { + "properties": { + "componentRecords": { + "const": [] + } + } + }, + "$defs": { + "Interest": { + "title": "Interest", + "description": "A description of an interest held by an interestedParty in the subject.", + "type": "object", + "properties": { + "type": { + "title": "Type of Interest", + "description": "The nature of the interest, using the interestType codelist.", + "type": "string", + "enum": [ + "shareholding", + "votingRights", + "appointmentOfBoard", + "otherInfluenceOrControl", + "seniorManagingOfficial", + "settlor", + "trustee", + "protector", + "beneficiaryOfLegalArrangement", + "rightsToSurplusAssetsOnDissolution", + "rightsToProfitOrIncome", + "rightsGrantedByContract", + "conditionalRightsGrantedByContract", + "controlViaCompanyRulesOrArticles", + "controlByLegalFramework", + "boardMember", + "boardChair", + "unknownInterest", + "unpublishedInterest", + "enjoymentAndUseOfAssets", + "rightToProfitOrIncomeFromAssets", + "nominee", + "nominator" + ], + "codelist": "interestType.csv", + "openCodelist": false + }, + "directOrIndirect": { + "title": "Direct or Indirect", + "description": "How directly the interest is exercised by the interested party. The value MUST be 'indirect' if intermediate entities or agents are known to exist, and MUST be 'direct' if such intermediaries are known not to exist. Otherwise the value MUST be 'unknown'.", + "type": "string", + "enum": [ + "direct", + "indirect", + "unknown" + ], + "codelist": "directOrIndirect.csv", + "openCodelist": false + }, + "beneficialOwnershipOrControl": { + "title": "Beneficial Ownership or Control", + "description": "Whether this interest (alone or with others) means the interested party is a beneficial owner of the subject. If 'true' the interested party MUST be a natural person. The definition of 'beneficial owner' in operation SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "boolean" + }, + "details": { + "title": "Details", + "description": "The local name given to this kind of interest, or further information (semi-structured or unstructured) to clarify the nature of the interest.", + "type": "string" + }, + "share": { + "title": "Percentage Share", + "description": "The proportion of this type of interest held by the interested party, where an interest is countable. Provide the `exact` percentage if known. Otherwise, `minimum` (or `exclusiveMinimum`) and `maximum` (or `exclusiveMaximum`) can be used to record the range into which the proportion falls. (The `minimum` and `maximum` values are inclusive.)", + "type": "object", + "properties": { + "exact": { + "title": "Exact percentage", + "description": "The exact share of this interest held (if available).", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "maximum": { + "title": "Maximum Percentage", + "description": "The inclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "minimum": { + "title": "Minimum Percentage", + "description": "The inclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMinimum": { + "title": "Exclusive Minimum percentage", + "description": "The exclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMaximum": { + "title": "Exclusive Maximum Percentage", + "description": "The exclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + } + } + }, + "startDate": { + "title": "Start Date", + "description": "The date from which this interest was active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this interest ceased to exist. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + } + } + } + } + } + } + } + } + ], + "required": [ + "statementId", + "declarationSubject", + "recordId", + "recordType", + "recordDetails", + "statementDate" + ] + }, + "$defs": { + "Statement": { + "title": "Statement", + "description": "A claim about a person, entity or relationship, made at a particular point in time.", + "type": "object", + "properties": { + "statementId": { + "title": "Statement Identifier", + "description": "A persistent globally unique identifier for this Statement. Length MUST be 32 - 64 characters (inclusive).", + "type": "string", + "minLength": 32, + "maxLength": 64 + }, + "statementDate": { + "title": "Statement Date", + "description": "The date on which this statement was declared by the source, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "annotations": { + "title": "Annotations", + "description": "Annotations about this Statement or parts of this Statement", + "type": "array", + "items": { + "title": "Annotation", + "description": "Additional information about the data contained in this Statement. Annotations can apply to a whole statement, an object or a single field. Custom properties can be included within the Annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this Annotation applies to, starting from the root of the Statement. An empty string (\"\") indicates that the Annotation applies to the whole Statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date on which this Annotation was created, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this Annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this Annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the person, organisation or agent that created this Annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The reason for this Annotation, using the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free text description providing extra information about part of this Statement.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed Content", + "description": "A representation of the Annotation target after the transformation in the `description` field has been applied. This field MUST only be used when the `motivation` is 'transformation'." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this Statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "allOf": [ + { + "if": { + "properties": { + "motivation": { + "const": "linking" + } + } + }, + "then": { + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + "else": { + "required": [ + "statementPointerTarget", + "motivation" + ] + } + }, + { + "if": { + "not": { + "properties": { + "motivation": { + "const": "transformation" + } + } + } + }, + "then": { + "properties": { + "transformedContent": { + "const": "" + } + } + } + } + ] + } + }, + "publicationDetails": { + "title": "Publication Details", + "description": "Information concerning the publication of this Statement.", + "type": "object", + "properties": { + "publicationDate": { + "title": "Publication date", + "description": "The date on which this statement was published, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "bodsVersion": { + "title": "BODS Version", + "description": "The version of the Beneficial Ownership Data Standard to which this Statement conforms, expressed as major.minor (e.g. 0.2 or 1.0). In a published BODS dataset, all Statements MUST have the same major version number.", + "type": "string", + "pattern": "^(\\d+\\.)(\\d+)$" + }, + "license": { + "title": "License URL", + "description": "A link to the license that applies to this Statement. The canonical URI of the license SHOULD be used. Publishers are encouraged to use a Public Domain Dedication or Open Definition Conformant (http://opendefinition.org/licenses/) license.", + "type": "string", + "format": "uri" + }, + "publisher": { + "type": "object", + "title": "Publisher", + "description": "Details of the organisation or person publishing a Statement.", + "properties": { + "name": { + "title": "Name", + "description": "The name of the publisher.", + "type": "string" + }, + "url": { + "title": "URL", + "description": "The URL where details of the full dataset, or of the publisher, can be found.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "url" + ] + } + ] + } + }, + "required": [ + "publicationDate", + "bodsVersion", + "publisher" + ] + }, + "source": { + "title": "Source", + "description": "Details describing an information source.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + }, + "declaration": { + "title": "Declaration Reference", + "description": "An identifier or reference for a declaration within the publisher\u2019s system. Where a Statement is a claim from a particular declaration (made at a point in time by a `source` about a `declarationSubject`) this field identifies the declaration.", + "type": "string" + }, + "declarationSubject": { + "title": "Declaration Subject", + "description": "A `recordId` value for the subject of a beneficial ownership network (always an entity or person).", + "type": "string" + }, + "recordId": { + "title": "Record Identifier", + "description": "A unique identifier for the record (within the publisher's system) to which this Statement relates. (A record captures information about an entity, natural person or relationship within the beneficial ownership network of a particular declaration subject.)", + "type": "string" + }, + "recordType": { + "title": "Record Type", + "description": "The type of record (within the publisher's system) to which this Statement relates: entity, person, or relationship.", + "type": "string", + "enum": [ + "entity", + "person", + "relationship" + ], + "codelist": "recordType.csv", + "openCodelist": false + }, + "recordStatus": { + "title": "Record Status", + "description": "The lifecycle status of the record (within the publisher's system) to which this Statement relates, using the recordStatus codelist.", + "type": "string", + "enum": [ + "new", + "updated", + "closed" + ], + "codelist": "recordStatus.csv", + "openCodelist": false + }, + "recordDetails": { + "title": "Record Details", + "description": "The details of the entity, person or relationship as declared on the Statement Date.", + "type": "object" + } + }, + "allOf": [ + { + "if": { + "properties": { + "recordType": { + "const": "entity" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:entity", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "title": "Entity Record Details", + "description": "Information about an entity.", + "type": "object", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this entity is a component in an indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this entity MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Entity Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Entity Statement SHOULD be considered when replacing the primary Relationship Statement. The primary Relationship statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "entityType": { + "type": "object", + "title": "Entity Type", + "description": "The form of the entity described in the Statement.", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "title": "Type", + "description": "The general form of the entity, using the entityType codelist.", + "codelist": "entityType.csv", + "enum": [ + "registeredEntity", + "legalEntity", + "arrangement", + "anonymousEntity", + "unknownEntity", + "state", + "stateBody" + ] + }, + "subtype": { + "type": "string", + "title": "Subtype", + "description": "The particular form of the entity, where relevant, using the entitySubtype codelist. The value MUST align with the `entityType` value.", + "codelist": "entitySubtype.csv", + "enum": [ + "governmentDepartment", + "stateAgency", + "other", + "trust", + "nomination" + ], + "openCodelist": false + }, + "details": { + "type": "string", + "title": "Details", + "description": "This may be used to provide a local name for this type of entity, or any further information to identify the type of entity. For example, in Finland 'ministeri\u00f6' for a government department." + } + }, + "propertyOrder": 4, + "allOf": [ + { + "if": { + "properties": { + "type": { + "enum": [ + "arrangement" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "trust", + "nomination", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "legalEntity" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "trust", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "stateBody" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "governmentDepartment", + "stateAgency", + "other" + ] + } + } + } + }, + { + "if": { + "properties": { + "type": { + "enum": [ + "registeredEntity", + "state", + "anonymousEntity", + "unknownEntity" + ] + } + } + }, + "then": { + "properties": { + "subtype": { + "enum": [ + "other" + ] + } + } + } + } + ] + }, + "unspecifiedEntityDetails": { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + }, + "name": { + "title": "Entity Name", + "description": "The declared name of this entity.", + "type": "string", + "propertyOrder": 10 + }, + "alternateNames": { + "title": "Alternative Names", + "description": "An array of other names this entity is known by.", + "type": "array", + "items": { + "type": "string", + "title": "Name", + "description": "A name this entity is known by." + }, + "propertyOrder": 12 + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this entity. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to a person or entity. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for a person or entity, as issued by the scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme Code", + "description": "For entities, a code from org-id.guide (https://www.org-id.guide) for an identifier-issuing authority (e.g. 'GB-COH'). For natural persons, a value with the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3166-1 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD.", + "type": "string" + }, + "schemeName": { + "title": "Scheme Name", + "description": "The name of the identifier-issuing authority.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "A canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) for the identifier and associated details of the person or entity, if one exists.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "foundingDate": { + "title": "Founding Date", + "description": "The date on which this entity was founded, created or registered. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date", + "propertyOrder": 30 + }, + "dissolutionDate": { + "title": "Dissolution Date", + "description": "The date on which this entity was dissolved or ceased, if it is no longer active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date", + "propertyOrder": 35 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this entity.", + "type": "array", + "items": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "propertyOrder": 40 + }, + "uri": { + "title": "URI", + "description": "Where a persistent URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) is available for this entity this should be included.", + "type": "string", + "format": "uri", + "propertyOrder": 21 + }, + "publicListing": { + "type": "object", + "title": "Public Listing", + "description": "Details of a publicly listed company, its securities (shares and other tradable financial instruments related to the entity), and related regulatory filings.", + "required": [ + "hasPublicListing" + ], + "minProperties": 1, + "properties": { + "hasPublicListing": { + "type": "boolean", + "title": "Has Public Listing", + "description": "Whether the entity is a publicly listed company." + }, + "companyFilingsURLs": { + "type": "array", + "title": "Company Filings URLs", + "description": "URL or URLs where regulatory filings related to major holdings can be retrieved. URLs may point to pages maintained by regulatory bodies, stock exchanges or by the company itself.", + "items": { + "type": "string", + "format": "uri" + } + }, + "securitiesListings": { + "type": "array", + "title": "Securities Listings", + "description": "Details of the entity's securities and the public exchanges and markets on which they are traded. All equity securities SHOULD be listed here, plus any other securities from which beneficial ownership might be derived. Where a security is traded on more than one market, there SHOULD be an entry for each market (or market segment).", + "items": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + }, + "formedByStatute": { + "type": "object", + "title": "Formed by Statute", + "description": "The law which mandated the formation of the entity described in the statement, where applicable. This information SHOULD be provided where a state has created an agency or other entity with specific legislation.", + "properties": { + "name": { + "type": "string", + "title": "Statute Name", + "description": "The name of the law. " + }, + "date": { + "type": "string", + "title": "Date", + "description": "The date on which the law came into force. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are not available, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "format": "date" + } + }, + "propertyOrder": 18 + } + }, + "required": [ + "isComponent", + "entityType" + ], + "$defs": { + "PublicListing": { + "type": "object", + "title": "Public Listing", + "description": "Details of a publicly listed company, its securities (shares and other tradable financial instruments related to the entity), and related regulatory filings.", + "required": [ + "hasPublicListing" + ], + "minProperties": 1, + "properties": { + "hasPublicListing": { + "type": "boolean", + "title": "Has Public Listing", + "description": "Whether the entity is a publicly listed company." + }, + "companyFilingsURLs": { + "type": "array", + "title": "Company Filings URLs", + "description": "URL or URLs where regulatory filings related to major holdings can be retrieved. URLs may point to pages maintained by regulatory bodies, stock exchanges or by the company itself.", + "items": { + "type": "string", + "format": "uri" + } + }, + "securitiesListings": { + "type": "array", + "title": "Securities Listings", + "description": "Details of the entity's securities and the public exchanges and markets on which they are traded. All equity securities SHOULD be listed here, plus any other securities from which beneficial ownership might be derived. Where a security is traded on more than one market, there SHOULD be an entry for each market (or market segment).", + "items": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + }, + "SecuritiesListing": { + "type": "object", + "title": "Securities Listing", + "description": "Details of a security and the market on which it is traded.", + "required": [ + "stockExchangeJurisdiction", + "security", + "stockExchangeName" + ], + "properties": { + "marketIdentifierCode": { + "type": "string", + "title": "Market Identifier Code (MIC)", + "description": "The Market Identifier Code (MIC) of the market on which the security is traded. Where the security is traded on a segment of an exchange, this is the MIC of the segment. Where it is traded on the main exchange, this is the MIC of the main exchange and MUST match the `operatingMarketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "operatingMarketIdentifierCode": { + "type": "string", + "title": "Operating Market Identifier Code (Operating MIC)", + "description": "The Market Identifier Code (MIC) of the main exchange or trading platform handling trades in this security. Where the security is traded on a segment of an exchange, this is the MIC of the parent exchange or trading platform. Where it is traded on the main exchange, this is the MIC of that main exchange and MUST match the `marketIdentifierCode`. MICs are allocated and managed under ISO standard 10383." + }, + "stockExchangeJurisdiction": { + "type": "string", + "title": "Stock Exchange Jurisdiction", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction under which the exchange, market or trading platform is regulated.", + "maxLength": 6, + "minLength": 2 + }, + "stockExchangeName": { + "type": "string", + "title": "Stock Exchange Name", + "description": "The name of the exchange, market or trading platform on which the security is traded. If the security is traded on a segment of the exchange, then the name SHOULD include both elements. For example, 'London Stock Exchange - MTF'." + }, + "security": { + "type": "object", + "title": "Security", + "description": "Identifying information of the stock or other security.", + "required": [ + "ticker" + ], + "properties": { + "idScheme": { + "type": "string", + "title": "Identifier Scheme", + "description": "The scheme under which the security has been issued a unique, persistent identifier, using the securitiesIdentifierSchemes codelist.", + "enum": [ + "isin", + "figi", + "cusip", + "cins" + ], + "codelist": "securitiesIdentifierSchemes.csv" + }, + "id": { + "type": "string", + "title": "Identifier", + "description": "The unique identifier of the security as issued under the `idScheme`." + }, + "ticker": { + "type": "string", + "title": "Stock Ticker", + "description": "The stock ticker identifying this security on the named stock exchange." + } + } + } + } + } + } + } + } + } + }, + { + "if": { + "properties": { + "recordType": { + "const": "person" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:person", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "type": "object", + "title": "Person Record Details", + "description": "Information about a natural person.", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this person is a component of an indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this person MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Person Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Person Statement SHOULD be considered when replacing the primary Relationship Statement. The primary Relationship Statement MUST have a `isComponent` value of 'false'.", + "type": "boolean" + }, + "personType": { + "title": "Person Type", + "description": "The status of this person, using the personType codelist. Where a person has the type 'anonymousPerson' or 'unknownPerson' a reason for the absence of information SHOULD be provided in 'unspecifiedPersonDetails'", + "type": "string", + "enum": [ + "anonymousPerson", + "unknownPerson", + "knownPerson" + ], + "propertyOrder": 4, + "codelist": "personType.csv", + "openCodelist": false + }, + "unspecifiedPersonDetails": { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + }, + "names": { + "title": "Names", + "description": "One or more known names for this person.", + "type": "array", + "items": { + "title": "Name", + "description": "A name by which this person is known. A name MUST be provided in `fullName`, and MAY be broken down in the `familyName`, `givenName` and `patronymicName` fields, based on the EC ISA Core Person Vocabulary (https://joinup.ec.europa.eu/solution/e-government-core-vocabularies) definitions.", + "type": "object", + "required": [ + "fullName" + ], + "properties": { + "type": { + "title": "Type", + "description": "The status of this name for the person, using the nameType codelist.", + "type": "string", + "enum": [ + "legal", + "translation", + "transliteration", + "former", + "alternative", + "birth" + ], + "codelist": "nameType.csv", + "openCodelist": false + }, + "fullName": { + "title": "Full Name", + "description": "The complete name of the person.", + "type": "string" + }, + "familyName": { + "title": "Family Name", + "description": "Part of the person's `fullName` which is shared by family members. The value may include prefixes or suffixes, e.g. 'de Boer', 'van de Putte', 'von und zu Orlow'. The value may be a multiple-part family name, such as are commonly found in Hispanic countries. For example, Miguel de Cervantes Saavedra's Family Name would be recorded as 'de Cervantes Saavedra.'", + "type": "string" + }, + "givenName": { + "title": "Given Names", + "description": "The part of the person's `fullName` that identifies the person within their family. These are given to a person by their parents at birth or may be legally recognised as 'given names' through a formal process. For example, the given name for Johann Sebastian Bach is 'Johann Sebastian'.", + "type": "string" + }, + "patronymicName": { + "title": "Patronymic Name", + "description": "Part of the person's `fullName` which is inherited from their father, as is common in countries such as Iceland, Ethiopia and Russia. For example, the 'Sergeyevich' in 'Mikhail Sergeyevich Gorbachev'.", + "type": "string" + } + } + }, + "propertyOrder": 10 + }, + "identifiers": { + "title": "Identifiers", + "description": "One or more official identifiers for this person. Where available, official registration numbers should be provided.", + "type": "array", + "items": { + "title": "Identifier", + "description": "An identifier that has been assigned to a person or entity. `scheme` or `schemeName` (or both) MUST be included in an Identifier object.", + "type": "object", + "properties": { + "id": { + "title": "ID", + "description": "The identifier for a person or entity, as issued by the scheme.", + "type": "string" + }, + "scheme": { + "title": "Scheme Code", + "description": "For entities, a code from org-id.guide (https://www.org-id.guide) for an identifier-issuing authority (e.g. 'GB-COH'). For natural persons, a value with the pattern {JURISDICTION}-{TYPE} where JURISDICTION is an ISO 3166-1 3-digit country code and TYPE is one of PASSPORT, TAXID or IDCARD.", + "type": "string" + }, + "schemeName": { + "title": "Scheme Name", + "description": "The name of the identifier-issuing authority.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "A canonical URI (https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) for the identifier and associated details of the person or entity, if one exists.", + "type": "string", + "format": "uri" + } + }, + "anyOf": [ + { + "required": [ + "scheme" + ] + }, + { + "required": [ + "schemeName" + ] + }, + { + "required": [ + "scheme", + "schemeName" + ] + } + ] + }, + "propertyOrder": 20 + }, + "nationalities": { + "title": "Nationality", + "description": "The nationalities held by this person.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 30 + }, + "placeOfBirth": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "birthDate": { + "title": "Date of Birth", + "description": "The date of birth for this person, in YYYY, YYYY-MM, or YYYY-MM-DD format.", + "type": "string", + "anyOf": [ + { + "pattern": "^(\\d{4})(-(1[0-2]|0[1-9]))?$" + }, + { + "format": "date" + } + ], + "propertyOrder": 35 + }, + "deathDate": { + "title": "Death Date", + "description": "The date of death for this person, in YYYY, YYYY-MM, or YYYY-MM-DD format.", + "type": "string", + "anyOf": [ + { + "pattern": "^(\\d{4})(-(1[0-2]|0[1-9]))?$" + }, + { + "format": "date" + } + ], + "propertyOrder": 36 + }, + "taxResidencies": { + "title": "Tax Residency", + "description": "The tax residencies held by this person, as an array of Country objects.", + "type": "array", + "items": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "propertyOrder": 55 + }, + "addresses": { + "title": "Addresses", + "description": "One or more addresses for this person.", + "type": "array", + "items": { + "title": "Address", + "description": "Semi-structured address details, suitable for processing using address-parsing algorithms. Where postal codes and country information are isolated fields in source systems, this information SHOULD be published in the dedicated fields and SHOULD NOT be published in the `address` field.", + "type": "object", + "properties": { + "type": { + "title": "Type", + "description": "The function of the address, using the addressType codelist.", + "type": "string", + "enum": [ + "placeOfBirth", + "residence", + "registered", + "service", + "alternative", + "business" + ], + "codelist": "addressType.csv", + "openCodelist": false + }, + "address": { + "title": "Address", + "description": "The address, with each line or component separated by a line-break or comma.", + "type": "string" + }, + "postCode": { + "title": "Postcode", + "description": "The postal code for this address.", + "type": "string" + }, + "country": { + "title": "Country", + "description": "A country MUST have a name. A country SHOULD have a 2-letter country code (ISO 3166-1)", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the country", + "type": "string" + }, + "code": { + "title": "Country Code", + "description": "The 2-letter country code (ISO 3166-1) for this country.", + "type": "string", + "maxLength": 2, + "minLength": 2 + } + }, + "required": [ + "name" + ] + } + } + }, + "propertyOrder": 60 + }, + "politicalExposure": { + "type": "object", + "title": "Political Exposure", + "description": "Information about whether, and how, the person described by this statement is politically exposed. Use this property only if politically exposed person (PEP) declarations are expected as part of beneficial ownership declarations.", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "title": "Politically Exposed Person (PEP) Status", + "description": "This value is 'isPep' or 'isNotPep' according to whether the person described by this statement has the status of politically exposed person (PEP). An 'unknown' value means a PEP status declaration is expected but missing; the reason for the missing data SHOULD be supplied in the `details` array.", + "enum": [ + "isPep", + "isNotPep", + "unknown" + ] + }, + "details": { + "type": "array", + "title": "Politically Exposed Person (PEP) Details", + "description": "One or more descriptions of this person's Politically Exposed Person (PEP) status.", + "items": { + "title": "PEP Status Details", + "description": "Information about a person's political involvement.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason for this person being declared a politically-exposed person.", + "type": "string" + }, + "missingInfoReason": { + "title": "Missing Information Reasons", + "description": "An explanation of why the PEP status for the person is not provided (i.e. `politicalExposure.status` is 'unknown'). This may be a standard descriptive phrase from the source system, or a free text justification. Where this field is present it should be the only field except for `source`.", + "type": "string" + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "startDate": { + "title": "State Date", + "description": "The date from which this person had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this person no longer had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "source": { + "title": "Source", + "description": "Details describing an information source.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + } + } + }, + "required": [ + "personType", + "isComponent" + ], + "$defs": { + "Name": { + "title": "Name", + "description": "A name by which this person is known. A name MUST be provided in `fullName`, and MAY be broken down in the `familyName`, `givenName` and `patronymicName` fields, based on the EC ISA Core Person Vocabulary (https://joinup.ec.europa.eu/solution/e-government-core-vocabularies) definitions.", + "type": "object", + "required": [ + "fullName" + ], + "properties": { + "type": { + "title": "Type", + "description": "The status of this name for the person, using the nameType codelist.", + "type": "string", + "enum": [ + "legal", + "translation", + "transliteration", + "former", + "alternative", + "birth" + ], + "codelist": "nameType.csv", + "openCodelist": false + }, + "fullName": { + "title": "Full Name", + "description": "The complete name of the person.", + "type": "string" + }, + "familyName": { + "title": "Family Name", + "description": "Part of the person's `fullName` which is shared by family members. The value may include prefixes or suffixes, e.g. 'de Boer', 'van de Putte', 'von und zu Orlow'. The value may be a multiple-part family name, such as are commonly found in Hispanic countries. For example, Miguel de Cervantes Saavedra's Family Name would be recorded as 'de Cervantes Saavedra.'", + "type": "string" + }, + "givenName": { + "title": "Given Names", + "description": "The part of the person's `fullName` that identifies the person within their family. These are given to a person by their parents at birth or may be legally recognised as 'given names' through a formal process. For example, the given name for Johann Sebastian Bach is 'Johann Sebastian'.", + "type": "string" + }, + "patronymicName": { + "title": "Patronymic Name", + "description": "Part of the person's `fullName` which is inherited from their father, as is common in countries such as Iceland, Ethiopia and Russia. For example, the 'Sergeyevich' in 'Mikhail Sergeyevich Gorbachev'.", + "type": "string" + } + } + }, + "PepStatusDetails": { + "title": "PEP Status Details", + "description": "Information about a person's political involvement.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason for this person being declared a politically-exposed person.", + "type": "string" + }, + "missingInfoReason": { + "title": "Missing Information Reasons", + "description": "An explanation of why the PEP status for the person is not provided (i.e. `politicalExposure.status` is 'unknown'). This may be a standard descriptive phrase from the source system, or a free text justification. Where this field is present it should be the only field except for `source`.", + "type": "string" + }, + "jurisdiction": { + "title": "Jurisdiction", + "description": "A Jurisdiction MUST have a name. A jurisdiction SHOULD have a 2-letter country code (ISO 3166-1) or a subdivision code (ISO 3166-2).", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the jurisdiction", + "type": "string" + }, + "code": { + "title": "Country or Subdivision Code", + "description": "The 2-letter country code (ISO 3166-1) or the subdivision code (ISO 3166-2) for the jurisdiction.", + "type": "string", + "maxLength": 6, + "minLength": 2 + } + }, + "required": [ + "name" + ] + }, + "startDate": { + "title": "State Date", + "description": "The date from which this person had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this person no longer had the status of a Politically-exposed Person (PEP). The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "source": { + "title": "Source", + "description": "Details describing an information source.", + "type": "object", + "properties": { + "type": { + "title": "Source Type", + "description": "The types of the source, using the sourceType codelist. Include 'verified' in the array if the information in the Statement has undergone a verification process.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "selfDeclaration", + "officialRegister", + "thirdParty", + "primaryResearch", + "verified" + ], + "codelist": "sourceType.csv", + "openCodelist": false + } + }, + "description": { + "title": "Description", + "description": "Additional, free text information about the source of information.", + "type": "string" + }, + "url": { + "title": "Source URL", + "description": "The external URL from which this information was fetched, if relevant. Or, if relevant, a URL providing additional detail on how this information was sourced.", + "type": "string", + "format": "uri" + }, + "retrievedAt": { + "title": "Retrieved At", + "description": "A timestamp indicating when this information was imported from an external system, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "assertedBy": { + "title": "Asserted By", + "description": "The people or organisations providing the information asserted in this Statement. This may include the declaring subject of a self-declaration, or the name of an agent making a declaration on their behalf. If this Statement has been verified, the array may include the name of the organisation providing verification.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the agent making the assertion", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the agent making the assertion", + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + } + } + } + }, + { + "if": { + "properties": { + "recordType": { + "const": "relationship" + } + } + }, + "then": { + "properties": { + "recordDetails": { + "$id": "urn:relationship", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "version": "0.4", + "title": "Relationship Record Details", + "description": "Information about the interests that an interested party (a person or entity) holds in the subject (an entity).", + "type": "object", + "properties": { + "isComponent": { + "title": "Is component", + "description": "Whether this relationship is a component of a wider indirect relationship. Where `isComponent` is 'true': (1) the `recordId` of this secondary Relationship Statement MUST be an element in the `componentRecords` array of that primary Relationship Statement, (2) this Relationship Statement MUST come before that primary Relationship Statement in a BODS package or stream, (3) the replacement of this Relationship Statement SHOULD be considered when replacing the primary Relationship Statement, and (4) the primary Relationship Statement MUST have an `isComponent` value of 'false'. Where `isComponent` is 'false', this Relationship Statement is the primary declaration of the relationship between the `subject` and the `interestedParty`.", + "type": "boolean" + }, + "componentRecords": { + "title": "Component Record IDs", + "description": "The `recordId` values of all component records that provide detail about this relationship between the `subject` and the `interestedParty` (if it is indirect). If this relationship has components, its own `isComponent` value MUST be 'false'.", + "type": "array", + "items": { + "type": "string" + } + }, + "subject": { + "title": "Subject", + "description": "The `recordId` for the subject of the relationship, or a reason why the subject cannot be specified. The subject MUST be an entity.", + "oneOf": [ + { + "type": "string" + }, + { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + ] + }, + "interestedParty": { + "title": "Interested Party", + "description": "The `recordId` for the interested party in the relationship, or an Unspecified Record object with a reason for why this information has not been disclosed. The interested party MAY be an entity or a person. An Unspecified Record SHOULD only be used where no information at all is known about interested parties beyond this point of the beneficial ownership network. If the interested party is known to be an entity or person but their particular identity is unavailable, a `recordId` for them SHOULD be provided here (and the their `recordDetails.[person|entity]Type` should indicate that they are anonymous or unknown).", + "oneOf": [ + { + "type": "string" + }, + { + "title": "Unspecified or unknown person or entity", + "description": "A `reason` MUST be supplied.", + "type": "object", + "properties": { + "reason": { + "title": "Reason", + "description": "The reason that a person or entity cannot be specified, using the unspecifiedReason codelist.", + "type": "string", + "enum": [ + "noBeneficialOwners", + "subjectUnableToConfirmOrIdentifyBeneficialOwner", + "interestedPartyHasNotProvidedInformation", + "subjectExemptFromDisclosure", + "interestedPartyExemptFromDisclosure", + "unknown", + "informationUnknownToPublisher" + ], + "codelist": "unspecifiedReason.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "Additional information about the absence of details for a person or entity. This field may be used to provide set phrases from a source system, or a free text explanation.", + "type": "string" + } + }, + "required": [ + "reason" + ] + } + ] + }, + "interests": { + "title": "Interests", + "description": "A description of the interests held by the interested party in the subject.", + "type": "array", + "items": { + "title": "Interest", + "description": "A description of an interest held by an interestedParty in the subject.", + "type": "object", + "properties": { + "type": { + "title": "Type of Interest", + "description": "The nature of the interest, using the interestType codelist.", + "type": "string", + "enum": [ + "shareholding", + "votingRights", + "appointmentOfBoard", + "otherInfluenceOrControl", + "seniorManagingOfficial", + "settlor", + "trustee", + "protector", + "beneficiaryOfLegalArrangement", + "rightsToSurplusAssetsOnDissolution", + "rightsToProfitOrIncome", + "rightsGrantedByContract", + "conditionalRightsGrantedByContract", + "controlViaCompanyRulesOrArticles", + "controlByLegalFramework", + "boardMember", + "boardChair", + "unknownInterest", + "unpublishedInterest", + "enjoymentAndUseOfAssets", + "rightToProfitOrIncomeFromAssets", + "nominee", + "nominator" + ], + "codelist": "interestType.csv", + "openCodelist": false + }, + "directOrIndirect": { + "title": "Direct or Indirect", + "description": "How directly the interest is exercised by the interested party. The value MUST be 'indirect' if intermediate entities or agents are known to exist, and MUST be 'direct' if such intermediaries are known not to exist. Otherwise the value MUST be 'unknown'.", + "type": "string", + "enum": [ + "direct", + "indirect", + "unknown" + ], + "codelist": "directOrIndirect.csv", + "openCodelist": false + }, + "beneficialOwnershipOrControl": { + "title": "Beneficial Ownership or Control", + "description": "Whether this interest (alone or with others) means the interested party is a beneficial owner of the subject. If 'true' the interested party MUST be a natural person. The definition of 'beneficial owner' in operation SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "boolean" + }, + "details": { + "title": "Details", + "description": "The local name given to this kind of interest, or further information (semi-structured or unstructured) to clarify the nature of the interest.", + "type": "string" + }, + "share": { + "title": "Percentage Share", + "description": "The proportion of this type of interest held by the interested party, where an interest is countable. Provide the `exact` percentage if known. Otherwise, `minimum` (or `exclusiveMinimum`) and `maximum` (or `exclusiveMaximum`) can be used to record the range into which the proportion falls. (The `minimum` and `maximum` values are inclusive.)", + "type": "object", + "properties": { + "exact": { + "title": "Exact percentage", + "description": "The exact share of this interest held (if available).", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "maximum": { + "title": "Maximum Percentage", + "description": "The inclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "minimum": { + "title": "Minimum Percentage", + "description": "The inclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMinimum": { + "title": "Exclusive Minimum percentage", + "description": "The exclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMaximum": { + "title": "Exclusive Maximum Percentage", + "description": "The exclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + } + } + }, + "startDate": { + "title": "Start Date", + "description": "The date from which this interest was active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this interest ceased to exist. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + } + } + } + } + }, + "required": [ + "isComponent", + "subject", + "interestedParty" + ], + "if": { + "properties": { + "isComponent": { + "const": true + } + } + }, + "then": { + "properties": { + "componentRecords": { + "const": [] + } + } + }, + "$defs": { + "Interest": { + "title": "Interest", + "description": "A description of an interest held by an interestedParty in the subject.", + "type": "object", + "properties": { + "type": { + "title": "Type of Interest", + "description": "The nature of the interest, using the interestType codelist.", + "type": "string", + "enum": [ + "shareholding", + "votingRights", + "appointmentOfBoard", + "otherInfluenceOrControl", + "seniorManagingOfficial", + "settlor", + "trustee", + "protector", + "beneficiaryOfLegalArrangement", + "rightsToSurplusAssetsOnDissolution", + "rightsToProfitOrIncome", + "rightsGrantedByContract", + "conditionalRightsGrantedByContract", + "controlViaCompanyRulesOrArticles", + "controlByLegalFramework", + "boardMember", + "boardChair", + "unknownInterest", + "unpublishedInterest", + "enjoymentAndUseOfAssets", + "rightToProfitOrIncomeFromAssets", + "nominee", + "nominator" + ], + "codelist": "interestType.csv", + "openCodelist": false + }, + "directOrIndirect": { + "title": "Direct or Indirect", + "description": "How directly the interest is exercised by the interested party. The value MUST be 'indirect' if intermediate entities or agents are known to exist, and MUST be 'direct' if such intermediaries are known not to exist. Otherwise the value MUST be 'unknown'.", + "type": "string", + "enum": [ + "direct", + "indirect", + "unknown" + ], + "codelist": "directOrIndirect.csv", + "openCodelist": false + }, + "beneficialOwnershipOrControl": { + "title": "Beneficial Ownership or Control", + "description": "Whether this interest (alone or with others) means the interested party is a beneficial owner of the subject. If 'true' the interested party MUST be a natural person. The definition of 'beneficial owner' in operation SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "boolean" + }, + "details": { + "title": "Details", + "description": "The local name given to this kind of interest, or further information (semi-structured or unstructured) to clarify the nature of the interest.", + "type": "string" + }, + "share": { + "title": "Percentage Share", + "description": "The proportion of this type of interest held by the interested party, where an interest is countable. Provide the `exact` percentage if known. Otherwise, `minimum` (or `exclusiveMinimum`) and `maximum` (or `exclusiveMaximum`) can be used to record the range into which the proportion falls. (The `minimum` and `maximum` values are inclusive.)", + "type": "object", + "properties": { + "exact": { + "title": "Exact percentage", + "description": "The exact share of this interest held (if available).", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "maximum": { + "title": "Maximum Percentage", + "description": "The inclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "minimum": { + "title": "Minimum Percentage", + "description": "The inclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMinimum": { + "title": "Exclusive Minimum percentage", + "description": "The exclusive lower bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + }, + "exclusiveMaximum": { + "title": "Exclusive Maximum Percentage", + "description": "The exclusive upper bound of the share of this interest.", + "type": "number", + "maximum": 100, + "minimum": 0 + } + } + }, + "startDate": { + "title": "Start Date", + "description": "The date from which this interest was active. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + }, + "endDate": { + "title": "End Date", + "description": "The date from which this interest ceased to exist. The date MUST be given in YYYY-MM-DD format. Where a precise month or date are unknown, the value may be rounded to the first day of the (first) month. This rounding SHOULD be noted in accompanying guidance (such as a publication policy or data use guide).", + "type": "string", + "format": "date" + } + } + } + } + } + } + } + } + ], + "required": [ + "statementId", + "declarationSubject", + "recordId", + "recordType", + "recordDetails", + "statementDate" + ] + }, + "Annotation": { + "title": "Annotation", + "description": "Additional information about the data contained in this Statement. Annotations can apply to a whole statement, an object or a single field. Custom properties can be included within the Annotation object to provide structured data where required.", + "type": "object", + "properties": { + "statementPointerTarget": { + "title": "Statement Fragment Pointer", + "description": "An RFC6901 JSON Pointer (https://tools.ietf.org/html/rfc6901) describing the target fragment of the statement that this Annotation applies to, starting from the root of the Statement. An empty string (\"\") indicates that the Annotation applies to the whole Statement.", + "type": "string" + }, + "creationDate": { + "title": "Creation Date", + "description": "The date on which this Annotation was created, in full-date (YYYY-MM-DD) or date-time (e.g. YYYY-MM-DDTHH:MM:SSZ) format. See the IETF RFC3339 standard, section 5.6.", + "type": "string", + "anyOf": [ + { + "format": "date" + }, + { + "format": "date-time" + } + ] + }, + "createdBy": { + "title": "Created By", + "description": "The person, organisation or agent that created this Annotation.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "The name of the person, organisation or agent that created this Annotation.", + "type": "string" + }, + "uri": { + "title": "URI", + "description": "An optional URI to identify the person, organisation or agent that created this Annotation.", + "type": "string", + "format": "uri" + } + } + }, + "motivation": { + "title": "Motivation", + "description": "The reason for this Annotation, using the annotationMotivation codelist.", + "type": "string", + "enum": [ + "commenting", + "correcting", + "identifying", + "linking", + "transformation" + ], + "codelist": "annotationMotivation.csv", + "openCodelist": false + }, + "description": { + "title": "Description", + "description": "A free text description providing extra information about part of this Statement.", + "type": "string" + }, + "transformedContent": { + "type": "string", + "title": "Transformed Content", + "description": "A representation of the Annotation target after the transformation in the `description` field has been applied. This field MUST only be used when the `motivation` is 'transformation'." + }, + "url": { + "title": "URL", + "description": "A linked resource that annotates, provides context for or enhances this Statement. The content of the resource, or the relationship to the statement, MAY be described in the `description` field. This field is REQUIRED if the value of `motivation` is 'linking'.", + "type": "string", + "format": "uri" + } + }, + "allOf": [ + { + "if": { + "properties": { + "motivation": { + "const": "linking" + } + } + }, + "then": { + "required": [ + "statementPointerTarget", + "motivation", + "url" + ] + }, + "else": { + "required": [ + "statementPointerTarget", + "motivation" + ] + } + }, + { + "if": { + "not": { + "properties": { + "motivation": { + "const": "transformation" + } + } + } + }, + "then": { + "properties": { + "transformedContent": { + "const": "" + } + } + } + } + ] + } + } +} diff --git a/tests/test_additional_fields.py b/tests/test_additional_fields.py new file mode 100644 index 0000000..6ffa459 --- /dev/null +++ b/tests/test_additional_fields.py @@ -0,0 +1,44 @@ +import json +import pytest + +from libcove2.common import get_additional_fields_info +from libcove2.common import schema_dict_fields_generator + +@pytest.fixture +def bods_data_0_3(): + """Data for BODS 0.3""" + with open("tests/fixtures/bods-data-0-3-0.json", "r") as read_file: + return json.load(read_file) + +@pytest.fixture +def schema_fields_0_3(): + """Schema fields for BODS 0.3""" + with open("tests/fixtures/schema-0-3-0.json", "r") as read_file: + return set(schema_dict_fields_generator(json.load(read_file))) + +@pytest.fixture +def bods_data_0_4(): + """Data for BODS 0.4""" + with open("tests/fixtures/bods-data-0-4-0.json", "r") as read_file: + return json.load(read_file) + +@pytest.fixture +def schema_fields_0_4(): + """Schema fields for BODS 0.4""" + with open("tests/fixtures/schema-0-4-0.json", "r") as read_file: + return set(schema_dict_fields_generator(json.load(read_file))) + +def test_additional_fields_0_3(bods_data_0_3, schema_fields_0_3): + + additional_fields = get_additional_fields_info(bods_data_0_3, schema_fields_0_3) + + assert len(additional_fields) == 0 + +def test_additional_fields_0_4(bods_data_0_4, schema_fields_0_4): + print(schema_fields_0_4) + + additional_fields = get_additional_fields_info(bods_data_0_4, schema_fields_0_4) + + print(additional_fields) + + assert len(additional_fields) == 0 diff --git a/tests/test_schema_dict_fields_generator.py b/tests/test_schema_dict_fields_generator.py new file mode 100644 index 0000000..6ad9896 --- /dev/null +++ b/tests/test_schema_dict_fields_generator.py @@ -0,0 +1,31 @@ +import json +import pytest + +from libcove2.common import get_additional_fields_info +from libcove2.common import schema_dict_fields_generator + +@pytest.fixture +def schema_0_3(): + """Schema for BODS 0.3""" + with open("tests/fixtures/schema-0-3-0.json", "r") as read_file: + return json.load(read_file) + +@pytest.fixture +def schema_0_4(): + """Schema for BODS 0.4""" + with open("tests/fixtures/schema-0-4-0.json", "r") as read_file: + return json.load(read_file) + +def test_schema_dict_fields_generator_0_3(schema_0_3): + + schema_fields = set(schema_dict_fields_generator(schema_0_3)) + + assert len(schema_fields) == 130 + +def test_schema_dict_fields_generator_0_4(schema_0_4): + + schema_fields = set(schema_dict_fields_generator(schema_0_4)) + + print(schema_fields) + + assert len(schema_fields) == 139