diff --git a/Cargo.lock b/Cargo.lock index 6489db9..0cd03a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "mailschema" -version = "0.1.2" +version = "0.1.3" dependencies = [ "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index bca990f..5271fca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mailschema" -version = "0.1.2" +version = "0.1.3" edition = "2021" rust-version = "1.70" description = "Embedded JSON Schemas for Mail Action Protocol and the MailSchema Registry" diff --git a/README.md b/README.md index 1658447..be782b6 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,26 @@ Rust 1.70 or newer is required. ## Use a schema ```rust -use mailschema::{Schema, CONTENT_REVIEW_0_1_CONTRACT, MAP_0_1_SCHEMA}; +use mailschema::{Schema, CONTENT_REVIEW_0_2_CONTRACT, MAP_0_1_SCHEMA}; assert_eq!(Schema::Map01.as_str(), MAP_0_1_SCHEMA); -let content_review = Schema::ContentReview01.as_str(); +let content_review = Schema::ContentReview02.as_str(); assert!(content_review.contains("Content Review")); -assert!(CONTENT_REVIEW_0_1_CONTRACT.contains("MapTypeContract")); +assert!(CONTENT_REVIEW_0_2_CONTRACT.contains("MapTypeContract")); ``` -The crate exposes four Draft 2020-12 documents: +The crate exposes five Draft 2020-12 documents: - `MAP_0_1_SCHEMA` - `CONTENT_REVIEW_0_1_SCHEMA` +- `CONTENT_REVIEW_0_2_SCHEMA` - `CONTRIBUTION_SCHEMA` - `RECORD_SCHEMA` Parse the strings with your JSON library and pass them to a Draft 2020-12 validator with format checking enabled. The crate deliberately does not select a validation engine for its consumers. -`CONTENT_REVIEW_0_1_CONTRACT` exposes the canonical type contract used by MAP wire messages. +`CONTENT_REVIEW_0_1_CONTRACT` and `CONTENT_REVIEW_0_2_CONTRACT` expose the immutable canonical type contracts used by MAP wire messages. New integrations should use 0.2. ## Trust boundary diff --git a/UPSTREAM.md b/UPSTREAM.md index 4d7b155..bc9b205 100644 --- a/UPSTREAM.md +++ b/UPSTREAM.md @@ -1,7 +1,14 @@ # Release provenance -Version `0.1.2` was prepared from [`mailschema/mailschema@eddc745`](https://github.com/mailschema/mailschema/commit/eddc7456910bf6a3c33de51c46ebf50f61ee7342). +Version `0.1.3` derives from [`mailschema/mailschema@f630ec5`](https://github.com/mailschema/mailschema/commit/f630ec5569e7167114fb2a39a10548febfa6b979). -The included contribution schema has SHA-256 digest `a8a241b4837971a6251bcc135c704283536f4fb825fbbaedaf1598c6e688d564`. The canonical schemas live in the main MailSchema repository; this repository owns the Rust package surface and its release history. +The bundled files are exact projections of that source commit and do not independently define MAP: -The unreleased MAP contract projection is derived from [`mailschema/mailschema@e2f2cc6`](https://github.com/mailschema/mailschema/commit/e2f2cc6983173e5aba1da27f1f8bff37336efd77). Its MAP schema digest is `c39befeecf8643e8beda1f53a8d1411482b68ddf14974f3806cfa95776103f85`; its Content Review schema digest is `10e2263c820ba3a6ef0381c377078e2c1f324c3b142a6f8caf92b298cc66c692`; and its Content Review contract byte digest is `754ab7245ddb09ff4da000fccc60d746724379d4146ea227973e5d87f105f800`. These files are exact projections of that source commit and do not independently define MAP. +- MAP 0.1 schema: `c39befeecf8643e8beda1f53a8d1411482b68ddf14974f3806cfa95776103f85` +- Content Review 0.1 schema: `10e2263c820ba3a6ef0381c377078e2c1f324c3b142a6f8caf92b298cc66c692` +- Content Review 0.1 contract: `754ab7245ddb09ff4da000fccc60d746724379d4146ea227973e5d87f105f800` +- Content Review 0.2 schema: `d2286ffe410cceae56f9caa145634fd9613f5ce51e11ba089cad67b9f62259b7` +- Content Review 0.2 contract: `3bd1cd4a86e00d00590eeb150b7b29cebece589058d6094a40aa9d497dc8efe0` +- Contribution schema: `a8a241b4837971a6251bcc135c704283536f4fb825fbbaedaf1598c6e688d564` + +The canonical contracts live in the main MailSchema repository. This repository owns the Rust package surface and its release history. diff --git a/contracts/content-review-0.2.json b/contracts/content-review-0.2.json new file mode 100644 index 0000000..7dec56a --- /dev/null +++ b/contracts/content-review-0.2.json @@ -0,0 +1,91 @@ +{ + "kind": "MapTypeContract", + "id": "https://mailschema.org/types/content-review", + "version": "0.2", + "profile": "https://mailschema.org/profiles/map/0.1", + "target": "Service-owned content at the exact revision and digest named in the request.", + "requestSchema": { + "url": "https://mailschema.org/schemas/content-review-0.2.schema.json", + "canonicalDigest": "sha-256:43a01e620e0730e47755694bdf5d086f8d0a1d3d8328fb0c7d2a4b70c6e62e25" + }, + "operations": [ + { + "id": "request-changes", + "effect": "Record review feedback on the named revision.", + "results": [ + { + "state": "accepted", + "outputSchema": { + "type": "object", + "additionalProperties": false, + "properties": { + "feedbackRecorded": { + "const": true + } + }, + "required": [ + "feedbackRecorded" + ] + } + } + ] + }, + { + "id": "approve", + "effect": "Record approval of the named revision, or record why a proposed approval ended without approval.", + "results": [ + { + "state": "approval-required", + "outputSchema": { + "type": "object", + "additionalProperties": false, + "properties": { + "approvalUrl": { + "type": "string", + "format": "uri", + "pattern": "^https://" + } + }, + "required": [ + "approvalUrl" + ] + } + }, + { + "state": "completed", + "outputSchema": { + "type": "object", + "additionalProperties": false, + "properties": { + "decision": { + "const": "approved" + } + }, + "required": [ + "decision" + ] + } + }, + { + "state": "failed", + "outputSchema": { + "type": "object", + "additionalProperties": false, + "properties": { + "reason": { + "enum": [ + "declined", + "stale-target", + "expired" + ] + } + }, + "required": [ + "reason" + ] + } + } + ] + } + ] +} diff --git a/schemas/content-review-0.2.schema.json b/schemas/content-review-0.2.schema.json new file mode 100644 index 0000000..88b5be7 --- /dev/null +++ b/schemas/content-review-0.2.schema.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://mailschema.org/schemas/content-review-0.2.schema.json", + "title": "Content Review 0.2 MAP request binding", + "allOf": [ + { "$ref": "https://mailschema.org/schemas/map-0.1.schema.json#/$defs/request" }, + { + "type": "object", + "properties": { + "type": { + "type": "object", + "properties": { + "id": { "const": "https://mailschema.org/types/content-review" }, + "version": { "const": "0.2" } + } + } + } + }, + { + "oneOf": [ + { + "type": "object", + "properties": { + "operation": { "const": "request-changes" }, + "input": { + "type": "object", + "additionalProperties": false, + "properties": { + "feedback": { + "type": "string", + "minLength": 1, + "maxLength": 12000, + "pattern": "\\S" + } + }, + "required": ["feedback"] + } + } + }, + { + "type": "object", + "properties": { + "operation": { "const": "approve" }, + "input": { + "type": "object", + "additionalProperties": false, + "maxProperties": 0 + } + } + } + ] + } + ] +} diff --git a/src/lib.rs b/src/lib.rs index d16a0b8..4ad9e7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,13 @@ pub const CONTENT_REVIEW_0_1_SCHEMA: &str = /// Canonical Content Review 0.1 type contract. pub const CONTENT_REVIEW_0_1_CONTRACT: &str = include_str!("../contracts/content-review-0.1.json"); +/// Content Review 0.2 request binding. +pub const CONTENT_REVIEW_0_2_SCHEMA: &str = + include_str!("../schemas/content-review-0.2.schema.json"); + +/// Canonical Content Review 0.2 type contract. +pub const CONTENT_REVIEW_0_2_CONTRACT: &str = include_str!("../contracts/content-review-0.2.json"); + /// Supported local schema documents. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Schema { @@ -28,6 +35,7 @@ pub enum Schema { Record, Map01, ContentReview01, + ContentReview02, } impl Schema { @@ -38,6 +46,7 @@ impl Schema { Self::Record => RECORD_SCHEMA, Self::Map01 => MAP_0_1_SCHEMA, Self::ContentReview01 => CONTENT_REVIEW_0_1_SCHEMA, + Self::ContentReview02 => CONTENT_REVIEW_0_2_SCHEMA, } } } @@ -53,6 +62,7 @@ mod tests { Schema::Record, Schema::Map01, Schema::ContentReview01, + Schema::ContentReview02, ] { let value: serde_json::Value = serde_json::from_str(schema.as_str()).unwrap(); assert_eq!( @@ -75,5 +85,8 @@ mod tests { contract["id"], "https://mailschema.org/types/content-review" ); + let current_contract: serde_json::Value = + serde_json::from_str(CONTENT_REVIEW_0_2_CONTRACT).unwrap(); + assert_eq!(current_contract["version"], "0.2"); } }