diff --git a/README.md b/README.md index 4756251..c8a240a 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,12 @@ First-party, versioned data contracts and transactional type packs for mdbase collections. +Record contracts describe compact, application-facing semantics rather than +storage layouts or external interchange formats. Their field names and schemas +should say what an application can rely on while leaving collections free to +choose local field names through explicit type mappings. Contract-specific +behavior such as workflow vocabularies belongs in a validated `binding_schema`. + Published contract schemas are immutable interoperability boundaries. A catalog-listed starter type contains an inline snapshot of its starting schema instead of inheriting that boundary. Once installed, the type belongs to the @@ -78,3 +84,10 @@ A standards-oriented contract must identify its normative references and state its profile scope. An mdbase contract is not presented as an official schema from the referenced standards body unless that body actually publishes it as such. + +External interchange schemas should not be listed as general-purpose record +contracts unless the installed type intentionally stores that exact shape. +Converters and exporters can consume a smaller semantic record contract and +produce the external format. Historical packs may set `catalog: false` to keep +their immutable artifact URLs available without advertising them for new +installations. diff --git a/contracts/mdbase.contact/1.0.0.md b/contracts/mdbase.contact/1.0.0.md new file mode 100644 index 0000000..eca51e4 --- /dev/null +++ b/contracts/mdbase.contact/1.0.0.md @@ -0,0 +1,22 @@ +--- +kind: mdbase.contract +contract_type: record +id: mdbase.contact +version: 1.0.0 +name: Contact +description: A compact application-facing view of a person or organisation. +record_schema: + dialect: json-schema-2020-12 + ref: ../../schemas/mdbase.contact/1.0.0.schema.json +--- + +# Contact + +This contract exposes the small set of contact semantics commonly shared by +address books, relationship tools, and other applications. A collection keeps +its own field names and may store richer local data; the implementing type maps +only the fields it wants applications to see. + +The contract is deliberately not an interchange format. Exporters can convert +this view to JSContact, vCard, or another wire representation without requiring +Markdown records to store that representation directly. diff --git a/dist/artifacts/contracts/mdbase.contact/1.0.0.md b/dist/artifacts/contracts/mdbase.contact/1.0.0.md new file mode 100644 index 0000000..eca51e4 --- /dev/null +++ b/dist/artifacts/contracts/mdbase.contact/1.0.0.md @@ -0,0 +1,22 @@ +--- +kind: mdbase.contract +contract_type: record +id: mdbase.contact +version: 1.0.0 +name: Contact +description: A compact application-facing view of a person or organisation. +record_schema: + dialect: json-schema-2020-12 + ref: ../../schemas/mdbase.contact/1.0.0.schema.json +--- + +# Contact + +This contract exposes the small set of contact semantics commonly shared by +address books, relationship tools, and other applications. A collection keeps +its own field names and may store richer local data; the implementing type maps +only the fields it wants applications to see. + +The contract is deliberately not an interchange format. Exporters can convert +this view to JSContact, vCard, or another wire representation without requiring +Markdown records to store that representation directly. diff --git a/dist/artifacts/schemas/mdbase.contact/1.0.0.schema.json b/dist/artifacts/schemas/mdbase.contact/1.0.0.schema.json new file mode 100644 index 0000000..51570d0 --- /dev/null +++ b/dist/artifacts/schemas/mdbase.contact/1.0.0.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/contracts/schemas/mdbase.contact/1.0.0.schema.json", + "title": "Contact", + "description": "A compact application-facing contact view.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "The name applications should use when presenting this contact." + }, + "kind": { + "type": "string", + "enum": ["individual", "organisation", "group"], + "description": "The broad kind of contact when the collection distinguishes it." + }, + "primary_email": { + "type": "string", + "format": "email", + "description": "The preferred email address for this contact." + }, + "primary_phone": { + "type": "string", + "minLength": 1, + "description": "The preferred telephone number for this contact." + }, + "organisation": { + "type": "string", + "minLength": 1, + "description": "The organisation most closely associated with this contact." + }, + "birthday": { + "type": "string", + "format": "date", + "description": "The contact's birthday when known." + } + }, + "additionalProperties": false +} diff --git a/dist/artifacts/types/contact/2.md b/dist/artifacts/types/contact/2.md new file mode 100644 index 0000000..38a862e --- /dev/null +++ b/dist/artifacts/types/contact/2.md @@ -0,0 +1,76 @@ +--- +kind: mdbase.type +name: contact +version: 1 +description: A person or organisation you want to stay in touch with +match: + where: + type: contact +schema: + dialect: json-schema-2020-12 + value: + $schema: https://json-schema.org/draft/2020-12/schema + title: Contact + description: A friendly local contact with room for collection-specific fields. + type: object + required: + - type + - name + properties: + type: + const: contact + name: + type: string + minLength: 1 + description: The name shown in contact lists. + kind: + type: string + enum: + - individual + - organisation + - group + default: individual + description: The broad kind of contact. + email: + type: string + format: email + description: The preferred email address. + phone: + type: string + minLength: 1 + description: The preferred telephone number. + organisation: + type: string + minLength: 1 + description: The contact's main organisation. + birthday: + type: string + format: date + description: The contact's birthday. + additionalProperties: true +collection: + display: + name_field: name + description_field: organisation + icon: address-book +implements: + - contract: mdbase.contact + version: 1.0.0 + fields: + name: name + kind: kind + primary_email: email + primary_phone: phone + organisation: organisation + birthday: birthday +--- + +# Contact + +Contact notes use familiar frontmatter fields and leave the Markdown body free +for history, context, and anything else worth remembering. Applications using +the `mdbase.contact` contract see only the mapped contact fields. + +You can rename or extend the local fields in mdbase-editor. Keep the contract +mapping aligned so other contact-aware applications continue to understand +the type. diff --git a/dist/catalog.json b/dist/catalog.json index 9fec696..bfdec6d 100644 --- a/dist/catalog.json +++ b/dist/catalog.json @@ -10,24 +10,14 @@ }, "contracts": [ { - "id": "mdbase.jscontact.card", - "version": "2.0.0", - "name": "JSContact Card 2.0 core", - "description": "A strict, portable core profile of an IETF JSContact 2.0 Card.", + "id": "mdbase.contact", + "version": "1.0.0", + "name": "Contact", + "description": "A compact application-facing view of a person or organisation.", "contract_type": "record", - "digest": "sha256:c56c5acbf7992155d6890294842a261fe80a933ec75a226ea875b97ba57dcaa2", - "artifact": "./artifacts/contracts/mdbase.jscontact.card/2.0.0.md", - "standards": [ - { - "name": "JSContact", - "version": "2.0", - "scope": "Strict core profile covering the Card envelope, names, email addresses, phones, organizations, and notes.", - "references": [ - "https://www.rfc-editor.org/rfc/rfc9553.html", - "https://www.rfc-editor.org/rfc/rfc9982.html" - ] - } - ] + "digest": "sha256:e3634a35737ada5eb62e3e15f1c0c9d2e27c55a3f98dfab94bbc14c40404903d", + "artifact": "./artifacts/contracts/mdbase.contact/1.0.0.md", + "standards": [] }, { "id": "mdbase.record.created", @@ -192,27 +182,27 @@ ], "packs": [ { - "id": "mdbase.jscontact", - "version": "2.0.3", + "id": "mdbase.contact", + "version": "1.0.0", "name": "Contact type pack", - "description": "The mdbase JSContact Card core contract and a fully expanded, editable Contact type.", - "digest": "sha256:e89693733a9d3d98bdd05fc040a08d7fb6f5eaea22089ed4ef8e0f1392e9c269", - "provision": "./packs/mdbase.jscontact/2.0.3.json", + "description": "A compact contact contract and a friendly, editable Contact type.", + "digest": "sha256:f5be1e7ea7b8dacda628d0cd809eb02cbad965505dc44c98bbd709ffb4847330", + "provision": "./packs/mdbase.contact/1.0.0.json", "provides": [ { - "id": "mdbase.jscontact.card", - "version": "2.0.0" + "id": "mdbase.contact", + "version": "1.0.0" } ], "resource_count": 3, "display": { "name": "Contact", - "summary": "Store people and organisations with names, email addresses, phone numbers, and notes.", + "summary": "Keep people and organisations with familiar names, email addresses, phone numbers, and birthdays.", "category": "people", "audience": "general", "icon": "address-book", "badges": [ - "JSContact 2.0" + "Portable contact semantics" ] }, "installation": { diff --git a/dist/packs/mdbase.contact/1.0.0.json b/dist/packs/mdbase.contact/1.0.0.json new file mode 100644 index 0000000..498a528 --- /dev/null +++ b/dist/packs/mdbase.contact/1.0.0.json @@ -0,0 +1,49 @@ +{ + "manifest": { + "kind": "mdbase.type-pack", + "id": "mdbase.contact", + "version": "1.0.0", + "name": "Contact type pack", + "description": "A compact contact contract and a friendly, editable Contact type.", + "resources": [ + { + "kind": "schema", + "source": "schemas/mdbase.contact/1.0.0.schema.json", + "target": "schemas/mdbase.contact/1.0.0.schema.json", + "digest": "sha256:bd8a011d18c71164b633f4e82cb33faa5b658cdba4f89312a34c13bf46a350d2" + }, + { + "kind": "contract", + "source": "contracts/mdbase.contact/1.0.0.md", + "target": "_contracts/mdbase.contact/1.0.0.md", + "digest": "sha256:e3634a35737ada5eb62e3e15f1c0c9d2e27c55a3f98dfab94bbc14c40404903d" + }, + { + "kind": "type", + "source": "types/contact/2.md", + "target": "_types/contact.md", + "digest": "sha256:c925ac22674b5fa9b1a7b8b3af827e5ce3ba15e423b64487f626f5ab4cc1c80a" + } + ] + }, + "resources": [ + { + "source": "schemas/mdbase.contact/1.0.0.schema.json", + "document": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://mdbase.dev/contracts/schemas/mdbase.contact/1.0.0.schema.json\",\n \"title\": \"Contact\",\n \"description\": \"A compact application-facing contact view.\",\n \"type\": \"object\",\n \"required\": [\"name\"],\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The name applications should use when presenting this contact.\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\"individual\", \"organisation\", \"group\"],\n \"description\": \"The broad kind of contact when the collection distinguishes it.\"\n },\n \"primary_email\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"description\": \"The preferred email address for this contact.\"\n },\n \"primary_phone\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The preferred telephone number for this contact.\"\n },\n \"organisation\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The organisation most closely associated with this contact.\"\n },\n \"birthday\": {\n \"type\": \"string\",\n \"format\": \"date\",\n \"description\": \"The contact's birthday when known.\"\n }\n },\n \"additionalProperties\": false\n}\n" + }, + { + "source": "contracts/mdbase.contact/1.0.0.md", + "document": "---\nkind: mdbase.contract\ncontract_type: record\nid: mdbase.contact\nversion: 1.0.0\nname: Contact\ndescription: A compact application-facing view of a person or organisation.\nrecord_schema:\n dialect: json-schema-2020-12\n ref: ../../schemas/mdbase.contact/1.0.0.schema.json\n---\n\n# Contact\n\nThis contract exposes the small set of contact semantics commonly shared by\naddress books, relationship tools, and other applications. A collection keeps\nits own field names and may store richer local data; the implementing type maps\nonly the fields it wants applications to see.\n\nThe contract is deliberately not an interchange format. Exporters can convert\nthis view to JSContact, vCard, or another wire representation without requiring\nMarkdown records to store that representation directly.\n" + }, + { + "source": "types/contact/2.md", + "document": "---\nkind: mdbase.type\nname: contact\nversion: 1\ndescription: A person or organisation you want to stay in touch with\nmatch:\n where:\n type: contact\nschema:\n dialect: json-schema-2020-12\n value:\n $schema: https://json-schema.org/draft/2020-12/schema\n title: Contact\n description: A friendly local contact with room for collection-specific fields.\n type: object\n required:\n - type\n - name\n properties:\n type:\n const: contact\n name:\n type: string\n minLength: 1\n description: The name shown in contact lists.\n kind:\n type: string\n enum:\n - individual\n - organisation\n - group\n default: individual\n description: The broad kind of contact.\n email:\n type: string\n format: email\n description: The preferred email address.\n phone:\n type: string\n minLength: 1\n description: The preferred telephone number.\n organisation:\n type: string\n minLength: 1\n description: The contact's main organisation.\n birthday:\n type: string\n format: date\n description: The contact's birthday.\n additionalProperties: true\ncollection:\n display:\n name_field: name\n description_field: organisation\n icon: address-book\nimplements:\n - contract: mdbase.contact\n version: 1.0.0\n fields:\n name: name\n kind: kind\n primary_email: email\n primary_phone: phone\n organisation: organisation\n birthday: birthday\n---\n\n# Contact\n\nContact notes use familiar frontmatter fields and leave the Markdown body free\nfor history, context, and anything else worth remembering. Applications using\nthe `mdbase.contact` contract see only the mapped contact fields.\n\nYou can rename or extend the local fields in mdbase-editor. Keep the contract\nmapping aligned so other contact-aware applications continue to understand\nthe type.\n" + } + ], + "provides": [ + { + "id": "mdbase.contact", + "version": "1.0.0" + } + ] +} diff --git a/dist/schemas/mdbase.contact/1.0.0.schema.json b/dist/schemas/mdbase.contact/1.0.0.schema.json new file mode 100644 index 0000000..51570d0 --- /dev/null +++ b/dist/schemas/mdbase.contact/1.0.0.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/contracts/schemas/mdbase.contact/1.0.0.schema.json", + "title": "Contact", + "description": "A compact application-facing contact view.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "The name applications should use when presenting this contact." + }, + "kind": { + "type": "string", + "enum": ["individual", "organisation", "group"], + "description": "The broad kind of contact when the collection distinguishes it." + }, + "primary_email": { + "type": "string", + "format": "email", + "description": "The preferred email address for this contact." + }, + "primary_phone": { + "type": "string", + "minLength": 1, + "description": "The preferred telephone number for this contact." + }, + "organisation": { + "type": "string", + "minLength": 1, + "description": "The organisation most closely associated with this contact." + }, + "birthday": { + "type": "string", + "format": "date", + "description": "The contact's birthday when known." + } + }, + "additionalProperties": false +} diff --git a/packs/mdbase.contact/1.0.0.pack.yaml b/packs/mdbase.contact/1.0.0.pack.yaml new file mode 100644 index 0000000..89ce08f --- /dev/null +++ b/packs/mdbase.contact/1.0.0.pack.yaml @@ -0,0 +1,31 @@ +kind: mdbase.catalog-pack +id: mdbase.contact +version: 1.0.0 +name: Contact type pack +description: A compact contact contract and a friendly, editable Contact type. +display: + name: Contact + summary: Keep people and organisations with familiar names, email addresses, phone numbers, and birthdays. + category: people + audience: general + icon: address-book + badges: + - Portable contact semantics +installation: + visibility: default + recommendation: user + primary_type: contact +expand_local_refs: true +provides: + - id: mdbase.contact + version: 1.0.0 +resources: + - kind: schema + source: schemas/mdbase.contact/1.0.0.schema.json + target: schemas/mdbase.contact/1.0.0.schema.json + - kind: contract + source: contracts/mdbase.contact/1.0.0.md + target: _contracts/mdbase.contact/1.0.0.md + - kind: type + source: types/contact/2.md + target: _types/contact.md diff --git a/packs/mdbase.jscontact/2.0.3.pack.yaml b/packs/mdbase.jscontact/2.0.3.pack.yaml index 4cb426e..cf54600 100644 --- a/packs/mdbase.jscontact/2.0.3.pack.yaml +++ b/packs/mdbase.jscontact/2.0.3.pack.yaml @@ -1,4 +1,5 @@ kind: mdbase.catalog-pack +catalog: false id: mdbase.jscontact version: 2.0.3 name: Contact type pack diff --git a/schemas/mdbase.contact/1.0.0.schema.json b/schemas/mdbase.contact/1.0.0.schema.json new file mode 100644 index 0000000..51570d0 --- /dev/null +++ b/schemas/mdbase.contact/1.0.0.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/contracts/schemas/mdbase.contact/1.0.0.schema.json", + "title": "Contact", + "description": "A compact application-facing contact view.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "The name applications should use when presenting this contact." + }, + "kind": { + "type": "string", + "enum": ["individual", "organisation", "group"], + "description": "The broad kind of contact when the collection distinguishes it." + }, + "primary_email": { + "type": "string", + "format": "email", + "description": "The preferred email address for this contact." + }, + "primary_phone": { + "type": "string", + "minLength": 1, + "description": "The preferred telephone number for this contact." + }, + "organisation": { + "type": "string", + "minLength": 1, + "description": "The organisation most closely associated with this contact." + }, + "birthday": { + "type": "string", + "format": "date", + "description": "The contact's birthday when known." + } + }, + "additionalProperties": false +} diff --git a/scripts/build.mjs b/scripts/build.mjs index 19c85e1..e2aed9a 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -68,7 +68,7 @@ for (const packFile of packFiles) { await writeFile(schemaPath, document); } - if (resource.kind === "contract") { + if (resource.kind === "contract" && definition.catalog !== false) { registerContract(resource.source, document, resourceDigest); } if (resource.kind === "type" && definition.catalog !== false) { diff --git a/types/contact/2.md b/types/contact/2.md new file mode 100644 index 0000000..38a862e --- /dev/null +++ b/types/contact/2.md @@ -0,0 +1,76 @@ +--- +kind: mdbase.type +name: contact +version: 1 +description: A person or organisation you want to stay in touch with +match: + where: + type: contact +schema: + dialect: json-schema-2020-12 + value: + $schema: https://json-schema.org/draft/2020-12/schema + title: Contact + description: A friendly local contact with room for collection-specific fields. + type: object + required: + - type + - name + properties: + type: + const: contact + name: + type: string + minLength: 1 + description: The name shown in contact lists. + kind: + type: string + enum: + - individual + - organisation + - group + default: individual + description: The broad kind of contact. + email: + type: string + format: email + description: The preferred email address. + phone: + type: string + minLength: 1 + description: The preferred telephone number. + organisation: + type: string + minLength: 1 + description: The contact's main organisation. + birthday: + type: string + format: date + description: The contact's birthday. + additionalProperties: true +collection: + display: + name_field: name + description_field: organisation + icon: address-book +implements: + - contract: mdbase.contact + version: 1.0.0 + fields: + name: name + kind: kind + primary_email: email + primary_phone: phone + organisation: organisation + birthday: birthday +--- + +# Contact + +Contact notes use familiar frontmatter fields and leave the Markdown body free +for history, context, and anything else worth remembering. Applications using +the `mdbase.contact` contract see only the mapped contact fields. + +You can rename or extend the local fields in mdbase-editor. Keep the contract +mapping aligned so other contact-aware applications continue to understand +the type.