Skip to main content

Blog website

A blog website publishes articles for people to read. Its content management system (CMS) gives the team a place to write posts, review them, and choose which versions appear on the website.

In this example, the people who manage content for a public garden's website are preparing an article for readers in the US and Mexico, in English and Spanish for each country. The headline and most of the article are the same within each language. One sentence tells readers when and where to see monarchs: at the garden during autumn migration in the US, or at the sanctuaries during winter in Mexico. A writer drafts the post, an editor reviews it, and a publisher makes the approved version available to readers.

The CMS uses Governed Artifact Protocol (GAP) to connect the writer's saved draft to the editor's review and the publisher's authorization. When the website retrieves the published post, it receives those records too. It can then check that the content it displays is the version the editor approved and the publisher authorized.

Saving, reviewing, and publishing remain separate actions in this CMS. Each carries out the GAP lifecycle steps or records the release decisions shown below:

A content designer proposes the post's fields as a profile, and the content model owner ratifies a revision that writers can reuse across posts.

A writer saves the post, and each save creates a new version while keeping the earlier ones.

An editor or reviewer approves or rejects one exact version. Either decision is recorded, and neither one releases the post.

The publisher authorizes the approved version, and the CMS releases it in the same action.

The website retrieves the released post and checks its release proof, which includes the editor's approval, the publisher's authorization, and any recorded rejection.

The blog post and its content model​

The CMS stores the monarch butterfly post as a GAP artifact with the ID blog-post:monarch-migration. Saving a change creates a new version of the post under that same ID, and earlier versions remain available. A profile defines the post's content model, including its fields and the rules they must satisfy. The blog post profile has four fields:

  • author is the byline: the name shown on the post.
  • date is the byline date and time, in RFC 3339 form, such as 2026-10-26T09:30:00Z. The writer sets it as part of the content; the moment of publication is recorded on the authorization.
  • audience is public, members, or internal, and the CMS uses it to choose which released posts each reader gets.
  • content holds a headline and body for each locale: a language and country identified by a BCP 47 tag. The model requires US English and Mexican Spanish. US Spanish and Mexican English are optional; a missing entry falls back to the required language for the same country, preserving that country’s advice.
LocaleRequired contentFallback if absent
US English (en-US)YesNone; the save fails
US Spanish (es-US)NoUS English (en-US)
Mexican English (en-MX)NoMexican Spanish (es-MX)
Mexican Spanish (es-MX)YesNone; the save fails

The CMS stores all authored locale variants in one payload. Approval and publication apply to that whole version, including every locale it contains.

The blog-post profile, revision 1JSON
{
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c",
"ratification": {
"ratifiedAt": "2026-08-26T00:00:00Z",
"actorId": "human:content-model-owner",
"actorKind": "human",
"reason": "The model supports English and Spanish for readers in the US and Mexico, requiring US English and Mexican Spanish, with fallback within each country."
},
"payloadContract": {
"type": "object",
"fields": {
"audience": {
"type": "string",
"enum": [
"public",
"members",
"internal"
]
},
"author": {
"type": "string",
"minLength": 1,
"maxLength": 5000
},
"content": {
"type": "localeMap",
"allowed": [
"en-US",
"es-US",
"en-MX",
"es-MX"
],
"required": [
"en-US",
"es-MX"
],
"fallback": {
"es-US": "en-US",
"en-MX": "es-MX"
},
"items": {
"type": "object",
"fields": {
"headline": {
"type": "string",
"minLength": 1,
"maxLength": 5000
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 5000
}
},
"required": [
"headline",
"body"
],
"additionalProperties": false
}
},
"date": {
"type": "string",
"format": "date-time"
}
},
"required": [
"audience",
"author",
"content",
"date"
],
"additionalProperties": false
}
}

Editing a headline creates a new version of the post using the same content model. Adding a required summary field changes the model itself, so the content model owner must ratify a new profile revision. Earlier post versions still reference the revision they were created under. Each post record's profile block includes the profile ID, revision number, and digest, so a reader can identify the exact rules used to check that version.

Example blog post content​

This is version 1 of blog-post:monarch-migration, exactly as the CMS stores it: the post's ID and version, the payload in all four locales, the profile revision it follows, and who saved it.

blog-post:monarch-migration, version 1JSON
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"authoredBy": {
"actorId": "agent:writer",
"actorKind": "agent"
},
"payload": {
"audience": "public",
"author": "Grounds staff",
"content": {
"en-US": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn the US, visit our garden during the autumn migration to see monarchs on their journey south. Check current opening dates and visitor guidance before planning your visit."
},
"es-US": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn Estados Unidos, visita nuestro jardín durante la migración de otoño para observar a las monarcas en su viaje hacia el sur. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
},
"en-MX": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn Mexico, visit the monarch sanctuaries in Michoacán and the State of Mexico during winter to see the overwintering colonies. Check current opening dates and visitor guidance before planning your visit."
},
"es-MX": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn México, visita los santuarios de la monarca en Michoacán y el Estado de México durante el invierno para observar las colonias que pasan allí la temporada. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
}
},
"date": "2026-10-26T09:30:00Z"
}
}

From draft to published post​

The monarch post moves from a writer's draft to the published page through these actions. Open the records under each action to see what the CMS stores.

Set up the content model​

Step 1: Propose a profileStep 2: Ratify a revision

A content designer proposes the post's fields, and the content model owner ratifies that exact profile revision, with a reason: "The model supports English and Spanish for readers in the US and Mexico, requiring US English and Mexican Spanish, with fallback within each country." Writers can use this ratified revision for any number of posts. Changing the content model requires a new revision.

Save a draft​

Step 3: Create a version

A writer saves the post. The CMS checks it against the profile revision and stores it as a new artifact version, keeping every earlier one. Until it is released, the post is a draft that only people and AI agents inside the CMS can see. When an editor asks for changes, the writer saves again, creating another version.

Approve or reject​

Release decision: ApprovalRelease decision: Rejection

The reviewer, an AI agent, reads version 1 and chooses Reject. The CMS records a release rejection for that exact version. This CMS requires a reason on every rejection, so the writer knows what to change: "The sentence about where to see monarchs gives different places and seasons for the US and Mexico. Please use the same advice in all four versions."

This CMS allows an editor to approve a version after a reviewer has rejected it. The editor, a person, reads version 1, considers the reviewer's objection, and chooses Approve. The CMS records a release approval tied to that exact version, down to its payload digest and profile revision, with the editor's reason: "The viewing advice should differ: readers in the US can visit the garden during autumn migration, while readers in Mexico can visit the sanctuaries during winter. The headline and the rest of the article match within each language. Approving all four versions as written." The post is still a draft, and the approval covers version 1 only. Once a version is released, the CMS accepts no new approvals of it, because an approval is a decision made before publication.

The seasonal advice reflects autumn migration in the US and winter sanctuary visits in Mexico.

The writer could instead revise the post and save a new version for review. The rejection would remain on the record of the earlier version.

The reviewer agent's rejection of version 1, with its reasonJSON
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"rejectedAt": "2026-10-26T08:30:00Z",
"rejectedBy": {
"actorId": "agent:local-reviewer",
"actorKind": "agent"
},
"reason": "The sentence about where to see monarchs gives different places and seasons for the US and Mexico. Please use the same advice in all four versions.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
}
The editor's approval of version 1, with its reasonJSON
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"approvedAt": "2026-10-26T09:00:00Z",
"approvedBy": {
"actorId": "human:editor",
"actorKind": "human"
},
"reason": "The viewing advice should differ: readers in the US can visit the garden during autumn migration, while readers in Mexico can visit the sanctuaries during winter. The headline and the rest of the article match within each language. Approving all four versions as written.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
}

Publish​

Step 4: AuthorizeStep 5: Release

A publisher reviews the approved version and chooses Publish. In one operation, the CMS records a release authorization and the release, and the post becomes available to readers. This CMS publishes a version only after it has been approved; GAP leaves it to each application whether to require that.

The publisher gives a reason too: "The editor has reviewed the regional advice for both countries. Publish all four versions together." The post's release proof now carries the reviewer's rejection, the editor's approval, and the publisher's authorization, each with its reason and each covering version 1 only.

The publisher's authorization of version 1JSON
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"authorizedAt": "2026-10-26T09:30:00Z",
"authorizedBy": {
"actorId": "human:publisher",
"actorKind": "human"
},
"reason": "The editor has reviewed the regional advice for both countries. Publish all four versions together.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
}
The release of version 1: the payload and its profile revisionJSON
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"payload": {
"audience": "public",
"author": "Grounds staff",
"content": {
"en-US": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn the US, visit our garden during the autumn migration to see monarchs on their journey south. Check current opening dates and visitor guidance before planning your visit."
},
"es-US": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn Estados Unidos, visita nuestro jardín durante la migración de otoño para observar a las monarcas en su viaje hacia el sur. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
},
"en-MX": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn Mexico, visit the monarch sanctuaries in Michoacán and the State of Mexico during winter to see the overwintering colonies. Check current opening dates and visitor guidance before planning your visit."
},
"es-MX": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn México, visita los santuarios de la monarca en Michoacán y el Estado de México durante el invierno para observar las colonias que pasan allí la temporada. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
}
},
"date": "2026-10-26T09:30:00Z"
}
}

Read the post​

Step 6: Read and verify

The website retrieves the released post and its release proof, checks the proof, and renders the content using its own templates. It shows the requested language when available, or uses the fallback defined in the profile. A reader who wants to inspect the publication decisions can check the same proof.

The release proof of version 1: the release, its profile revision, the rejection, the approval, and the authorizationJSON
{
"release": {
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"payload": {
"audience": "public",
"author": "Grounds staff",
"content": {
"en-US": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn the US, visit our garden during the autumn migration to see monarchs on their journey south. Check current opening dates and visitor guidance before planning your visit."
},
"es-US": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn Estados Unidos, visita nuestro jardín durante la migración de otoño para observar a las monarcas en su viaje hacia el sur. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
},
"en-MX": {
"headline": "Following the monarch migration",
"body": "The monarchs passing through our public garden are on their way to the mountain forests of central Mexico, where they spend the winter. In the garden, they stop to feed on nectar before continuing south.\n\nVolunteers record sightings along the garden paths. These observations help us follow the migration from year to year.\n\nIn Mexico, visit the monarch sanctuaries in Michoacán and the State of Mexico during winter to see the overwintering colonies. Check current opening dates and visitor guidance before planning your visit."
},
"es-MX": {
"headline": "Siguiendo la migración de las monarcas",
"body": "Las monarcas que pasan por nuestro jardín público van rumbo a los bosques de montaña del centro de México, donde pasan el invierno. En el jardín, se detienen para alimentarse de néctar antes de continuar hacia el sur.\n\nUn grupo de voluntarios registra los avistamientos en los senderos del jardín. Estas observaciones nos ayudan a seguir la migración de un año a otro.\n\nEn México, visita los santuarios de la monarca en Michoacán y el Estado de México durante el invierno para observar las colonias que pasan allí la temporada. Consulta las fechas de apertura y las recomendaciones para visitantes antes de planear tu visita."
}
},
"date": "2026-10-26T09:30:00Z"
}
},
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c",
"ratification": {
"ratifiedAt": "2026-08-26T00:00:00Z",
"actorId": "human:content-model-owner",
"actorKind": "human",
"reason": "The model supports English and Spanish for readers in the US and Mexico, requiring US English and Mexican Spanish, with fallback within each country."
},
"payloadContract": {
"type": "object",
"fields": {
"audience": {
"type": "string",
"enum": [
"public",
"members",
"internal"
]
},
"author": {
"type": "string",
"minLength": 1,
"maxLength": 5000
},
"content": {
"type": "localeMap",
"allowed": [
"en-US",
"es-US",
"en-MX",
"es-MX"
],
"required": [
"en-US",
"es-MX"
],
"fallback": {
"es-US": "en-US",
"en-MX": "es-MX"
},
"items": {
"type": "object",
"fields": {
"headline": {
"type": "string",
"minLength": 1,
"maxLength": 5000
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 5000
}
},
"required": [
"headline",
"body"
],
"additionalProperties": false
}
},
"date": {
"type": "string",
"format": "date-time"
}
},
"required": [
"audience",
"author",
"content",
"date"
],
"additionalProperties": false
}
},
"authorization": {
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"authorizedAt": "2026-10-26T09:30:00Z",
"authorizedBy": {
"actorId": "human:publisher",
"actorKind": "human"
},
"reason": "The editor has reviewed the regional advice for both countries. Publish all four versions together.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
},
"approvals": [
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"approvedAt": "2026-10-26T09:00:00Z",
"approvedBy": {
"actorId": "human:editor",
"actorKind": "human"
},
"reason": "The viewing advice should differ: readers in the US can visit the garden during autumn migration, while readers in Mexico can visit the sanctuaries during winter. The headline and the rest of the article match within each language. Approving all four versions as written.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
}
],
"rejections": [
{
"artifactId": "blog-post:monarch-migration",
"artifactVersion": 1,
"payloadDigest": "sha256:1bb260ea04ff3ff33f1f6d4c4f6f173a214cc6292864fd5f8e711e0198b4b194",
"profile": {
"profileId": "blog-post",
"revision": 1,
"digest": "sha256:e35800ae49f6649be07f9c95a4168ac468095de71974cf05ea7edcfe4016e61c"
},
"rejectedAt": "2026-10-26T08:30:00Z",
"rejectedBy": {
"actorId": "agent:local-reviewer",
"actorKind": "agent"
},
"reason": "The sentence about where to see monarchs gives different places and seasons for the US and Mexico. Please use the same advice in all four versions.",
"authorizationSubjectDigest": "sha256:3d0bbc5e92fe956200e8729848bf17d6c43522bdb568d37aff9094c2bd116ecb"
}
]
}

Why each decision was made​

The content model owner, reviewer, editor, and publisher each give a reason for their decision. The release proof includes those decisions and reasons. Someone inspecting it later can read the reviewer's objection, the editor's response, and the publisher's explanation alongside the recorded names and times.

The record attributes the reason to the person or AI agent who made the decision. The decision identifies the same version whether or not a reason is supplied; the reason is excluded when GAP calculates the digests. GAP makes reasons optional; when supplied, they must contain text. This CMS also limits reasons to 5,000 characters and requires one on every rejection.

Who does what?​

The CMS decides who may draft, approve, and publish, and GAP lets a person or an AI agent hold any of those permissions. In this example, the writer and the reviewer are AI agents, and the editor and the publisher are people. GAP's roles treat them all the same.

The writer acts as Author. The reviewer and the editor act as Authority when they reject or approve a version, and the publisher acts as Authority when publishing it. The CMS grants each of those permissions separately, so being able to approve doesn't mean being able to publish. For the content model, the content designer is the Author and the content model owner is the Authority. An editor who revises a post is acting as Author.

The CMS is the Implementation: it checks content, keeps the records, and controls release. The website is a Consumer of released content.

Driving the specification​

The blog demo implements the working draft independently of the other demos. Building the editorial workflow helps identify rules that are missing or unclear. Those findings lead to draft changes or are recorded as open questions. The example records are updated when the draft changes.

Run the demo​

The local demo models this workflow through tools an AI agent can call. It returns the released post and its records without rendering a website.

The blog website is one of three applications in the GAP demo, which runs on your computer with made-up data. Set up the demo once, then follow the blog website walkthrough, which goes from setting up the content model to a published post and its proof in about ten minutes. The tool reference lists every tool this application offers, with the lifecycle steps and decisions each one declares.

To compare these choices with your own work, use the evaluation guide.