From e15b2c849ce41cc2c8cde24af822058cd2ffa7e5 Mon Sep 17 00:00:00 2001 From: callumalpass Date: Wed, 29 Jul 2026 08:30:12 +1000 Subject: [PATCH] feat: present catalog types by audience --- public/contracts/artifacts/types/contact/1.md | 224 ++++++++++++++++++ public/contracts/catalog.json | 93 +++++++- .../packs/mdbase.jscontact/2.0.3.json | 49 ++++ .../contracts/schemas/catalog.v2.schema.json | 193 +++++++++++++++ scripts/sync-contracts.mjs | 3 +- site-sources.json | 2 +- src/data/contracts.json | 93 +++++++- src/pages/contracts/index.astro | 208 +++++++++++++--- 8 files changed, 816 insertions(+), 49 deletions(-) create mode 100644 public/contracts/artifacts/types/contact/1.md create mode 100644 public/contracts/packs/mdbase.jscontact/2.0.3.json create mode 100644 public/contracts/schemas/catalog.v2.schema.json diff --git a/public/contracts/artifacts/types/contact/1.md b/public/contracts/artifacts/types/contact/1.md new file mode 100644 index 0000000..7cbc9fc --- /dev/null +++ b/public/contracts/artifacts/types/contact/1.md @@ -0,0 +1,224 @@ +--- +kind: mdbase.type +name: contact +version: 1 +description: A fully expanded, editable Markdown-backed Contact using JSContact 2.0 +match: + where: + /@type: Card + version: "2.0" +schema: + dialect: json-schema-2020-12 + value: + $schema: https://json-schema.org/draft/2020-12/schema + title: Contact + description: A local starting shape for a person or organisation using IETF JSContact 2.0. + type: object + required: + - "@type" + - version + properties: + "@type": + const: Card + version: + const: "2.0" + uid: + type: string + minLength: 1 + kind: + enum: + - individual + - group + - org + - location + - device + - application + name: + type: object + properties: + "@type": + const: Name + components: + type: array + minItems: 1 + contains: + type: object + required: + - kind + properties: + kind: + not: + const: separator + items: + type: object + required: + - kind + - value + properties: + "@type": + const: NameComponent + kind: + enum: + - credential + - generation + - given + - given2 + - separator + - surname + - surname2 + - title + value: + type: string + additionalProperties: false + full: + type: string + minLength: 1 + isOrdered: + type: boolean + defaultSeparator: + type: string + anyOf: + - required: + - components + - required: + - full + additionalProperties: false + emails: + type: object + propertyNames: + type: string + minLength: 1 + additionalProperties: + type: object + required: + - address + properties: + "@type": + const: EmailAddress + address: + type: string + format: email + contexts: + type: object + additionalProperties: + const: true + pref: + type: integer + minimum: 1 + label: + type: string + additionalProperties: false + phones: + type: object + propertyNames: + type: string + minLength: 1 + additionalProperties: + type: object + required: + - number + properties: + "@type": + const: Phone + number: + type: string + minLength: 1 + features: + type: object + additionalProperties: + const: true + contexts: + type: object + additionalProperties: + const: true + pref: + type: integer + minimum: 1 + label: + type: string + additionalProperties: false + organizations: + type: object + propertyNames: + type: string + minLength: 1 + additionalProperties: + type: object + properties: + "@type": + const: Organization + name: + type: string + minLength: 1 + units: + type: array + minItems: 1 + items: + type: object + required: + - name + properties: + "@type": + const: OrgUnit + name: + type: string + minLength: 1 + additionalProperties: false + sortAs: + type: string + contexts: + type: object + additionalProperties: + const: true + anyOf: + - required: + - name + - required: + - units + additionalProperties: false + notes: + type: object + propertyNames: + type: string + minLength: 1 + additionalProperties: + type: object + required: + - note + properties: + "@type": + const: Note + note: + type: string + created: + type: string + format: date-time + additionalProperties: false + additionalProperties: false +collection: + display: + name_field: /name/full +implements: + - contract: mdbase.jscontact.card + version: 2.0.0 + fields: + /@type: /@type + version: version + uid: uid + kind: kind + name: name + emails: emails + phones: phones + organizations: organizations + notes: notes +--- + +# Contact + +This type begins as a fully expanded local copy of the JSContact core profile. +Nested fields are declared inline so the type editor can edit them directly. +Its fields belong to the collection and can be added, renamed, or reshaped. +Update the explicit contract mapping whenever a compatible field moves. + +The separately installed contract schema remains the portable boundary. Local +fields that are not mapped into that boundary remain collection-specific. diff --git a/public/contracts/catalog.json b/public/contracts/catalog.json index 2758817..9fec696 100644 --- a/public/contracts/catalog.json +++ b/public/contracts/catalog.json @@ -1,5 +1,5 @@ { - "catalog_version": 1, + "catalog_version": 2, "id": "dev.mdbase.first-party", "name": "mdbase contracts", "description": "Reviewed first-party contracts and starter type packs for mdbase collections.", @@ -193,11 +193,11 @@ "packs": [ { "id": "mdbase.jscontact", - "version": "2.0.2", - "name": "JSContact 2.0 starter", - "description": "The mdbase JSContact Card core contract and a fully expanded, editable Markdown implementation.", - "digest": "sha256:f6f5aa76850c10b83d42c0fffb7f76d3a67b531fb1de7bb5ae9a9b2c783687b0", - "provision": "./packs/mdbase.jscontact/2.0.2.json", + "version": "2.0.3", + "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", "provides": [ { "id": "mdbase.jscontact.card", @@ -205,7 +205,27 @@ } ], "resource_count": 3, - "featured": true + "display": { + "name": "Contact", + "summary": "Store people and organisations with names, email addresses, phone numbers, and notes.", + "category": "people", + "audience": "general", + "icon": "address-book", + "badges": [ + "JSContact 2.0" + ] + }, + "installation": { + "visibility": "default", + "recommendation": "user", + "primary_type": "contact", + "types": [ + { + "name": "contact", + "label": "Contact" + } + ] + } }, { "id": "mdbase.runtime.standard", @@ -257,7 +277,64 @@ } ], "resource_count": 43, - "featured": true + "display": { + "name": "Runtime standard library", + "summary": "Internal records and contracts for durable workflows, runs, timers, and diagnostics.", + "category": "infrastructure", + "audience": "infrastructure", + "icon": "terminal-window", + "badges": [ + "Runtime 0.2" + ] + }, + "installation": { + "visibility": "advanced", + "recommendation": "integration-managed", + "primary_type": null, + "caution": "Most collections do not need this pack. Install it only when a runtime integration asks you to.", + "types": [ + { + "name": "runtime_workflow", + "label": "Runtime workflow" + }, + { + "name": "runtime_policy", + "label": "Runtime policy" + }, + { + "name": "runtime_provider_registration", + "label": "Runtime provider registration" + }, + { + "name": "runtime_capability_grant", + "label": "Runtime capability grant" + }, + { + "name": "runtime_run", + "label": "Runtime run" + }, + { + "name": "runtime_action_attempt", + "label": "Runtime action attempt" + }, + { + "name": "runtime_checkpoint", + "label": "Runtime checkpoint" + }, + { + "name": "runtime_timer", + "label": "Runtime timer" + }, + { + "name": "runtime_diagnostic", + "label": "Runtime diagnostic" + }, + { + "name": "runtime_dead_letter", + "label": "Runtime dead letter" + } + ] + } } ] } diff --git a/public/contracts/packs/mdbase.jscontact/2.0.3.json b/public/contracts/packs/mdbase.jscontact/2.0.3.json new file mode 100644 index 0000000..7597779 --- /dev/null +++ b/public/contracts/packs/mdbase.jscontact/2.0.3.json @@ -0,0 +1,49 @@ +{ + "manifest": { + "kind": "mdbase.type-pack", + "id": "mdbase.jscontact", + "version": "2.0.3", + "name": "Contact type pack", + "description": "The mdbase JSContact Card core contract and a fully expanded, editable Contact type.", + "resources": [ + { + "kind": "schema", + "source": "schemas/mdbase.jscontact.card/2.0.0.schema.json", + "target": "schemas/mdbase.jscontact.card/2.0.0.schema.json", + "digest": "sha256:e2831b1203303075767aefd5e4892c81793d4b85c45db706ef189aa6124f8e26" + }, + { + "kind": "contract", + "source": "contracts/mdbase.jscontact.card/2.0.0.md", + "target": "_contracts/mdbase.jscontact.card/2.0.0.md", + "digest": "sha256:c56c5acbf7992155d6890294842a261fe80a933ec75a226ea875b97ba57dcaa2" + }, + { + "kind": "type", + "source": "types/contact/1.md", + "target": "_types/contact.md", + "digest": "sha256:3a7723ea8ad3e2bc1b10a33c2c77c974557df2471a91dea2c0db2e8e8a54e2ef" + } + ] + }, + "resources": [ + { + "source": "schemas/mdbase.jscontact.card/2.0.0.schema.json", + "document": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://mdbase.dev/contracts/schemas/mdbase.jscontact.card/2.0.0.schema.json\",\n \"title\": \"JSContact Card 2.0 core profile\",\n \"description\": \"A strict mdbase core profile of an IETF JSContact 2.0 Card.\",\n \"type\": \"object\",\n \"required\": [\"@type\", \"version\"],\n \"properties\": {\n \"@type\": { \"const\": \"Card\" },\n \"version\": { \"const\": \"2.0\" },\n \"uid\": { \"type\": \"string\", \"minLength\": 1 },\n \"kind\": {\n \"enum\": [\"individual\", \"group\", \"org\", \"location\", \"device\", \"application\"]\n },\n \"name\": { \"$ref\": \"#/$defs/name\" },\n \"emails\": {\n \"type\": \"object\",\n \"propertyNames\": { \"$ref\": \"#/$defs/id\" },\n \"additionalProperties\": { \"$ref\": \"#/$defs/emailAddress\" }\n },\n \"phones\": {\n \"type\": \"object\",\n \"propertyNames\": { \"$ref\": \"#/$defs/id\" },\n \"additionalProperties\": { \"$ref\": \"#/$defs/phone\" }\n },\n \"organizations\": {\n \"type\": \"object\",\n \"propertyNames\": { \"$ref\": \"#/$defs/id\" },\n \"additionalProperties\": { \"$ref\": \"#/$defs/organization\" }\n },\n \"notes\": {\n \"type\": \"object\",\n \"propertyNames\": { \"$ref\": \"#/$defs/id\" },\n \"additionalProperties\": { \"$ref\": \"#/$defs/note\" }\n }\n },\n \"additionalProperties\": false,\n \"$defs\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"trueSet\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"const\": true }\n },\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"@type\": { \"const\": \"Name\" },\n \"components\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"contains\": {\n \"type\": \"object\",\n \"required\": [\"kind\"],\n \"properties\": {\n \"kind\": { \"not\": { \"const\": \"separator\" } }\n }\n },\n \"items\": { \"$ref\": \"#/$defs/nameComponent\" }\n },\n \"full\": { \"type\": \"string\", \"minLength\": 1 },\n \"isOrdered\": { \"type\": \"boolean\" },\n \"defaultSeparator\": { \"type\": \"string\" }\n },\n \"anyOf\": [\n { \"required\": [\"components\"] },\n { \"required\": [\"full\"] }\n ],\n \"additionalProperties\": false\n },\n \"nameComponent\": {\n \"type\": \"object\",\n \"required\": [\"kind\", \"value\"],\n \"properties\": {\n \"@type\": { \"const\": \"NameComponent\" },\n \"kind\": {\n \"enum\": [\n \"credential\",\n \"generation\",\n \"given\",\n \"given2\",\n \"separator\",\n \"surname\",\n \"surname2\",\n \"title\"\n ]\n },\n \"value\": { \"type\": \"string\" }\n },\n \"additionalProperties\": false\n },\n \"emailAddress\": {\n \"type\": \"object\",\n \"required\": [\"address\"],\n \"properties\": {\n \"@type\": { \"const\": \"EmailAddress\" },\n \"address\": { \"type\": \"string\", \"format\": \"email\" },\n \"contexts\": { \"$ref\": \"#/$defs/trueSet\" },\n \"pref\": { \"type\": \"integer\", \"minimum\": 1 },\n \"label\": { \"type\": \"string\" }\n },\n \"additionalProperties\": false\n },\n \"phone\": {\n \"type\": \"object\",\n \"required\": [\"number\"],\n \"properties\": {\n \"@type\": { \"const\": \"Phone\" },\n \"number\": { \"type\": \"string\", \"minLength\": 1 },\n \"features\": { \"$ref\": \"#/$defs/trueSet\" },\n \"contexts\": { \"$ref\": \"#/$defs/trueSet\" },\n \"pref\": { \"type\": \"integer\", \"minimum\": 1 },\n \"label\": { \"type\": \"string\" }\n },\n \"additionalProperties\": false\n },\n \"organization\": {\n \"type\": \"object\",\n \"properties\": {\n \"@type\": { \"const\": \"Organization\" },\n \"name\": { \"type\": \"string\", \"minLength\": 1 },\n \"units\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/$defs/orgUnit\" }\n },\n \"sortAs\": { \"type\": \"string\" },\n \"contexts\": { \"$ref\": \"#/$defs/trueSet\" }\n },\n \"anyOf\": [\n { \"required\": [\"name\"] },\n { \"required\": [\"units\"] }\n ],\n \"additionalProperties\": false\n },\n \"orgUnit\": {\n \"type\": \"object\",\n \"required\": [\"name\"],\n \"properties\": {\n \"@type\": { \"const\": \"OrgUnit\" },\n \"name\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"additionalProperties\": false\n },\n \"note\": {\n \"type\": \"object\",\n \"required\": [\"note\"],\n \"properties\": {\n \"@type\": { \"const\": \"Note\" },\n \"note\": { \"type\": \"string\" },\n \"created\": { \"type\": \"string\", \"format\": \"date-time\" }\n },\n \"additionalProperties\": false\n }\n }\n}\n\n" + }, + { + "source": "contracts/mdbase.jscontact.card/2.0.0.md", + "document": "---\nkind: mdbase.contract\ncontract_type: record\nid: mdbase.jscontact.card\nversion: 2.0.0\nname: JSContact Card 2.0 core\ndescription: A strict, portable core profile of an IETF JSContact 2.0 Card.\nrecord_schema:\n dialect: json-schema-2020-12\n ref: ../../schemas/mdbase.jscontact.card/2.0.0.schema.json\nx-standard:\n name: JSContact\n version: \"2.0\"\n scope: Strict core profile covering the Card envelope, names, email addresses, phones, organizations, and notes.\n references:\n - https://www.rfc-editor.org/rfc/rfc9553.html\n - https://www.rfc-editor.org/rfc/rfc9982.html\n---\n\n# JSContact Card 2.0 core\n\nThis contract provides a deliberately bounded JSContact Card representation\nfor interoperable contact records. It follows JSContact 2.0, including the\noptional `uid` introduced by RFC 9982.\n\nThe profile accepts a strict subset of JSContact properties. It is not an\nofficial IETF JSON Schema and does not claim to validate every JSContact\nextension or conditional semantic rule.\n\n" + }, + { + "source": "types/contact/1.md", + "document": "---\nkind: mdbase.type\nname: contact\nversion: 1\ndescription: A fully expanded, editable Markdown-backed Contact using JSContact 2.0\nmatch:\n where:\n /@type: Card\n version: \"2.0\"\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 local starting shape for a person or organisation using IETF JSContact 2.0.\n type: object\n required:\n - \"@type\"\n - version\n properties:\n \"@type\":\n const: Card\n version:\n const: \"2.0\"\n uid:\n type: string\n minLength: 1\n kind:\n enum:\n - individual\n - group\n - org\n - location\n - device\n - application\n name:\n type: object\n properties:\n \"@type\":\n const: Name\n components:\n type: array\n minItems: 1\n contains:\n type: object\n required:\n - kind\n properties:\n kind:\n not:\n const: separator\n items:\n type: object\n required:\n - kind\n - value\n properties:\n \"@type\":\n const: NameComponent\n kind:\n enum:\n - credential\n - generation\n - given\n - given2\n - separator\n - surname\n - surname2\n - title\n value:\n type: string\n additionalProperties: false\n full:\n type: string\n minLength: 1\n isOrdered:\n type: boolean\n defaultSeparator:\n type: string\n anyOf:\n - required:\n - components\n - required:\n - full\n additionalProperties: false\n emails:\n type: object\n propertyNames:\n type: string\n minLength: 1\n additionalProperties:\n type: object\n required:\n - address\n properties:\n \"@type\":\n const: EmailAddress\n address:\n type: string\n format: email\n contexts:\n type: object\n additionalProperties:\n const: true\n pref:\n type: integer\n minimum: 1\n label:\n type: string\n additionalProperties: false\n phones:\n type: object\n propertyNames:\n type: string\n minLength: 1\n additionalProperties:\n type: object\n required:\n - number\n properties:\n \"@type\":\n const: Phone\n number:\n type: string\n minLength: 1\n features:\n type: object\n additionalProperties:\n const: true\n contexts:\n type: object\n additionalProperties:\n const: true\n pref:\n type: integer\n minimum: 1\n label:\n type: string\n additionalProperties: false\n organizations:\n type: object\n propertyNames:\n type: string\n minLength: 1\n additionalProperties:\n type: object\n properties:\n \"@type\":\n const: Organization\n name:\n type: string\n minLength: 1\n units:\n type: array\n minItems: 1\n items:\n type: object\n required:\n - name\n properties:\n \"@type\":\n const: OrgUnit\n name:\n type: string\n minLength: 1\n additionalProperties: false\n sortAs:\n type: string\n contexts:\n type: object\n additionalProperties:\n const: true\n anyOf:\n - required:\n - name\n - required:\n - units\n additionalProperties: false\n notes:\n type: object\n propertyNames:\n type: string\n minLength: 1\n additionalProperties:\n type: object\n required:\n - note\n properties:\n \"@type\":\n const: Note\n note:\n type: string\n created:\n type: string\n format: date-time\n additionalProperties: false\n additionalProperties: false\ncollection:\n display:\n name_field: /name/full\nimplements:\n - contract: mdbase.jscontact.card\n version: 2.0.0\n fields:\n /@type: /@type\n version: version\n uid: uid\n kind: kind\n name: name\n emails: emails\n phones: phones\n organizations: organizations\n notes: notes\n---\n\n# Contact\n\nThis type begins as a fully expanded local copy of the JSContact core profile.\nNested fields are declared inline so the type editor can edit them directly.\nIts fields belong to the collection and can be added, renamed, or reshaped.\nUpdate the explicit contract mapping whenever a compatible field moves.\n\nThe separately installed contract schema remains the portable boundary. Local\nfields that are not mapped into that boundary remain collection-specific.\n" + } + ], + "provides": [ + { + "id": "mdbase.jscontact.card", + "version": "2.0.0" + } + ] +} diff --git a/public/contracts/schemas/catalog.v2.schema.json b/public/contracts/schemas/catalog.v2.schema.json new file mode 100644 index 0000000..a60f9a3 --- /dev/null +++ b/public/contracts/schemas/catalog.v2.schema.json @@ -0,0 +1,193 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mdbase.dev/contracts/schemas/catalog.v2.schema.json", + "title": "mdbase contract catalog v2", + "type": "object", + "required": [ + "catalog_version", + "id", + "name", + "description", + "homepage", + "publisher", + "contracts", + "packs" + ], + "properties": { + "catalog_version": { "const": 2 }, + "id": { "$ref": "#/$defs/id" }, + "name": { "type": "string", "minLength": 1 }, + "description": { "type": "string", "minLength": 1 }, + "homepage": { "type": "string", "format": "uri" }, + "publisher": { + "type": "object", + "required": ["name", "url"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "url": { "type": "string", "format": "uri" } + }, + "additionalProperties": false + }, + "contracts": { + "type": "array", + "items": { "$ref": "#/$defs/contract" } + }, + "packs": { + "type": "array", + "items": { "$ref": "#/$defs/pack" } + } + }, + "additionalProperties": false, + "$defs": { + "id": { + "type": "string", + "minLength": 3, + "maxLength": 128, + "pattern": "^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)+$" + }, + "version": { + "type": "string", + "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$" + }, + "digest": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + }, + "relativeUrl": { + "type": "string", + "pattern": "^\\./(?!.*(?:^|/)\\.\\.(?:/|$)).+$" + }, + "contractRef": { + "type": "object", + "required": ["id", "version"], + "properties": { + "id": { "$ref": "#/$defs/id" }, + "version": { "$ref": "#/$defs/version" } + }, + "additionalProperties": false + }, + "standard": { + "type": "object", + "required": ["name", "version", "scope", "references"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "version": { "type": "string", "minLength": 1 }, + "scope": { "type": "string", "minLength": 1 }, + "references": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "format": "uri" } + } + }, + "additionalProperties": false + }, + "contract": { + "type": "object", + "required": [ + "id", + "version", + "name", + "description", + "contract_type", + "digest", + "artifact", + "standards" + ], + "properties": { + "id": { "$ref": "#/$defs/id" }, + "version": { "$ref": "#/$defs/version" }, + "name": { "type": "string", "minLength": 1 }, + "description": { "type": "string", "minLength": 1 }, + "contract_type": { "enum": ["record", "event", "action"] }, + "digest": { "$ref": "#/$defs/digest" }, + "artifact": { "$ref": "#/$defs/relativeUrl" }, + "standards": { + "type": "array", + "items": { "$ref": "#/$defs/standard" } + } + }, + "additionalProperties": false + }, + "display": { + "type": "object", + "required": ["name", "summary", "category", "audience", "icon"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "summary": { "type": "string", "minLength": 1 }, + "category": { + "enum": ["people", "work", "research", "calendar", "infrastructure", "other"] + }, + "audience": { "enum": ["general", "developer", "infrastructure"] }, + "icon": { "type": "string", "minLength": 1 }, + "badges": { + "type": "array", + "items": { "type": "string", "minLength": 1 }, + "uniqueItems": true + } + }, + "additionalProperties": false + }, + "installedType": { + "type": "object", + "required": ["name", "label"], + "properties": { + "name": { "type": "string", "minLength": 1 }, + "label": { "type": "string", "minLength": 1 } + }, + "additionalProperties": false + }, + "installation": { + "type": "object", + "required": ["visibility", "recommendation", "primary_type", "types"], + "properties": { + "visibility": { "enum": ["default", "advanced", "hidden"] }, + "recommendation": { "enum": ["user", "optional", "integration-managed"] }, + "primary_type": { + "oneOf": [ + { "type": "string", "minLength": 1 }, + { "type": "null" } + ] + }, + "types": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#/$defs/installedType" } + }, + "caution": { "type": "string", "minLength": 1 } + }, + "additionalProperties": false + }, + "pack": { + "type": "object", + "required": [ + "id", + "version", + "name", + "description", + "digest", + "provision", + "provides", + "resource_count", + "display", + "installation" + ], + "properties": { + "id": { "$ref": "#/$defs/id" }, + "version": { "$ref": "#/$defs/version" }, + "name": { "type": "string", "minLength": 1 }, + "description": { "type": "string", "minLength": 1 }, + "digest": { "$ref": "#/$defs/digest" }, + "provision": { "$ref": "#/$defs/relativeUrl" }, + "provides": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#/$defs/contractRef" } + }, + "resource_count": { "type": "integer", "minimum": 1 }, + "display": { "$ref": "#/$defs/display" }, + "installation": { "$ref": "#/$defs/installation" } + }, + "additionalProperties": false + } + } +} diff --git a/scripts/sync-contracts.mjs b/scripts/sync-contracts.mjs index e0e3d3b..746ab02 100644 --- a/scripts/sync-contracts.mjs +++ b/scripts/sync-contracts.mjs @@ -22,7 +22,7 @@ required(source, "Built contract catalog"); required(catalogPath, "Contract catalog index"); const catalog = JSON.parse(readFileSync(catalogPath, "utf8")); -if (catalog.catalog_version !== 1 || !Array.isArray(catalog.contracts) || !Array.isArray(catalog.packs)) { +if (catalog.catalog_version !== 2 || !Array.isArray(catalog.contracts) || !Array.isArray(catalog.packs)) { throw new Error("The contract catalog has an unsupported shape."); } @@ -38,4 +38,3 @@ console.log( function required(path, label) { if (!existsSync(path)) throw new Error(`${label} is missing: ${path}`); } - diff --git a/site-sources.json b/site-sources.json index a98abd3..adb932e 100644 --- a/site-sources.json +++ b/site-sources.json @@ -9,7 +9,7 @@ }, "contracts": { "repository": "mdbase-dev/mdbase-contracts", - "ref": "d58e5a4b22b61b6ed341ef9ef30e2874a434e87c" + "ref": "2870400a023ecbab21ca64bad4f6367dc5316433" }, "implementations": [ { diff --git a/src/data/contracts.json b/src/data/contracts.json index 2758817..9fec696 100644 --- a/src/data/contracts.json +++ b/src/data/contracts.json @@ -1,5 +1,5 @@ { - "catalog_version": 1, + "catalog_version": 2, "id": "dev.mdbase.first-party", "name": "mdbase contracts", "description": "Reviewed first-party contracts and starter type packs for mdbase collections.", @@ -193,11 +193,11 @@ "packs": [ { "id": "mdbase.jscontact", - "version": "2.0.2", - "name": "JSContact 2.0 starter", - "description": "The mdbase JSContact Card core contract and a fully expanded, editable Markdown implementation.", - "digest": "sha256:f6f5aa76850c10b83d42c0fffb7f76d3a67b531fb1de7bb5ae9a9b2c783687b0", - "provision": "./packs/mdbase.jscontact/2.0.2.json", + "version": "2.0.3", + "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", "provides": [ { "id": "mdbase.jscontact.card", @@ -205,7 +205,27 @@ } ], "resource_count": 3, - "featured": true + "display": { + "name": "Contact", + "summary": "Store people and organisations with names, email addresses, phone numbers, and notes.", + "category": "people", + "audience": "general", + "icon": "address-book", + "badges": [ + "JSContact 2.0" + ] + }, + "installation": { + "visibility": "default", + "recommendation": "user", + "primary_type": "contact", + "types": [ + { + "name": "contact", + "label": "Contact" + } + ] + } }, { "id": "mdbase.runtime.standard", @@ -257,7 +277,64 @@ } ], "resource_count": 43, - "featured": true + "display": { + "name": "Runtime standard library", + "summary": "Internal records and contracts for durable workflows, runs, timers, and diagnostics.", + "category": "infrastructure", + "audience": "infrastructure", + "icon": "terminal-window", + "badges": [ + "Runtime 0.2" + ] + }, + "installation": { + "visibility": "advanced", + "recommendation": "integration-managed", + "primary_type": null, + "caution": "Most collections do not need this pack. Install it only when a runtime integration asks you to.", + "types": [ + { + "name": "runtime_workflow", + "label": "Runtime workflow" + }, + { + "name": "runtime_policy", + "label": "Runtime policy" + }, + { + "name": "runtime_provider_registration", + "label": "Runtime provider registration" + }, + { + "name": "runtime_capability_grant", + "label": "Runtime capability grant" + }, + { + "name": "runtime_run", + "label": "Runtime run" + }, + { + "name": "runtime_action_attempt", + "label": "Runtime action attempt" + }, + { + "name": "runtime_checkpoint", + "label": "Runtime checkpoint" + }, + { + "name": "runtime_timer", + "label": "Runtime timer" + }, + { + "name": "runtime_diagnostic", + "label": "Runtime diagnostic" + }, + { + "name": "runtime_dead_letter", + "label": "Runtime dead letter" + } + ] + } } ] } diff --git a/src/pages/contracts/index.astro b/src/pages/contracts/index.astro index 38b51e8..3bb383f 100644 --- a/src/pages/contracts/index.astro +++ b/src/pages/contracts/index.astro @@ -3,6 +3,8 @@ import BaseLayout from "../../layouts/BaseLayout.astro"; import catalog from "../../data/contracts.json"; const artifactHref = (path: string) => `/contracts/${path.replace(/^\.\//, "")}`; +const readyMadePacks = catalog.packs.filter((pack) => pack.installation.visibility === "default"); +const advancedPacks = catalog.packs.filter((pack) => pack.installation.visibility === "advanced"); --- `/contracts/${path.replace(/^\.\//, "")}`
-

Installable packs

- - - - - - - - - - - { - catalog.packs.map((pack) => ( - - - - - - - )) - } - -
PackVersionProvidesProvision
- {pack.name}
- {pack.id} -
{pack.version} - {pack.provides.map((provided) => ( - {provided.id}@{provided.version} - ))} - Pack JSON
+

Ready-made types

+

+ Add these from Types → Add a type in mdbase-editor. + Each pack creates a local, editable type with its portable contract and + initial field mapping. +

+
+ { + readyMadePacks.map((pack) => ( +
+
+
+

{pack.display.name}

+

{pack.display.summary}

+
+ {pack.installation.types.length === 1 + ? "1 type" + : `${pack.installation.types.length} types`} +
+
+ {pack.display.badges?.map((badge) => {badge})} +
+
+ Technical details +

{pack.id}@{pack.version}

+

{pack.provides.length} {pack.provides.length === 1 ? "contract" : "contracts"} · {pack.resource_count} resources

+ View pack JSON +
+
+ )) + } +
+ { + advancedPacks.length > 0 && ( +
+ + + Developer and infrastructure packs + For integrations and specialised setups + + {advancedPacks.length} + +
+ {advancedPacks.map((pack) => ( +
+
+
+

{pack.display.name}

+

{pack.display.summary}

+
+ {pack.installation.types.length} types +
+ {pack.installation.caution &&

{pack.installation.caution}

} +
+ Technical details +

{pack.id}@{pack.version}

+

{pack.provides.length} contracts · {pack.resource_count} resources

+ View pack JSON +
+
+ ))} +
+
+ ) + }
Published versions are immutable.

@@ -112,3 +149,114 @@ const artifactHref = (path: string) => `/contracts/${path.replace(/^\.\//, "")}`

+