Skip to content

Governed Drupal CMS AI Ecosystem

Master Architecture, Upstream Ownership Standard, Product/Factory Contract, and AMCS Delivery Specification

Author: Thomas Scola, Founder, Bluefly.io System: Governed Drupal CMS / Agent-Managed Content System (AMCS) Primary Runtime: Drupal CMS 2.1.x on Drupal 11.4.x Forward Compatibility Target: Drupal 12, without prematurely moving production to unsupported or development-only dependencies Source Authority: GitLab Product Authority: Drupal Core + accepted Drupal contrib + Recipes + Site Templates Factory Authority: Gas City Work Ledger: Beads / Dolt Governing Principle: Build with Drupal. Own less code.

Replacement notice (2026-09-02): this document rebuilds and replaces the prior "Governed Drupal CMS AI Ecosystem" architecture as a full replacement, not an addendum. It removes architecture that prematurely declared Bluefly custom systems as owners, incorporates the product/factory and Beads corrections established in Bluefly's own Gas City work, and updates the Drupal baseline against upstream as of September 2, 2026. The original document explicitly called for contrib-first but then immediately promoted custom kb_cache, VectorBridge, Cedar/ContractPlane, bespoke tools, and a hash/Merkle subsystem into the target architecture; that contradiction is corrected below.

Historical inputs, not current architecture (confirmed 2026-09-10, bc-vb5z): products/Site-Factory/BlueflyAgents.com/01-BLUEFLY-CMS-REBUILD.md and the Manus app at products/Site-Factory/architecture/bluefly-cms-architecture/ (exported as “Bluefly.io CMS 2.0 Architecture Plan”; hosted blueflycms-wbd8akzs.manus.space returned 404). Keep useful site-migration requirements from those sources. Do not treat their OSSA/DUADP/StateMesh/DrupalCon inventory as the AMCS install specification.

0. Source Hierarchy and Decision Law

This document is governed by a source hierarchy.

For Drupal questions: 1. Read current Drupal core documentation. 2. Read the current Drupal.org project page and release information for the relevant contrib project. 3. Inspect the actual installed Composer dependency graph. 4. Inspect the module's supported APIs, plugins, configuration entities, Recipes, Tools, ECA actions, FlowDrop node types, and extension points. 5. Inspect existing Bluefly-owned Drupal projects. 6. Only after all of those fail may Bluefly create additional implementation.

For Gas City, Gas Town, Packs, Formulas, Orders, Rigs, Agents, Beads, or Dolt questions: 1. Read the relevant current Gas City upstream documentation. 2. Read the linked specification or internal contract when it defines the behavior. 3. Establish upstream behavior. 4. Compare Bluefly source against upstream. 5. Compare runtime state against Bluefly source. 6. Do not create a Bluefly mechanism for behavior Gas City already owns.

No architectural decision may begin with "How should Bluefly implement this?" until the prior question has been answered: "Who already owns this capability?"

1. Executive Verdict

The Governed Drupal CMS is not a collection of custom AI services wrapped around Drupal. It is a Drupal product in which agents operate as governed actors inside Drupal's existing authority model.

The fundamental law remains: Agents propose and perform bounded operations. Drupal governs state and executes authoritative transitions.

Drupal owns: content entities; fields and typed data; revisions; permissions; users and service identities; Content Moderation; configuration; workflows and publishing state; Canvas content and components; access decisions; durable business state.

Agents may: draft; inspect; classify; recommend; validate; execute approved Tools; run bounded workflows; add findings; create revisions; request or perform specifically authorized moderation transitions.

Agents do not become a parallel CMS. They do not own an independent content database, independent publication state, independent permissions model, independent workflow state, or independent authoritative memory store.

Human editors + governed agents
                │
                ▼
       Drupal interaction surfaces
       Canvas / UI / API / MCP
                │
                ▼
      Drupal identity + permissions
                │
                ▼
       Drupal entities + revisions
                │
                ▼
        Content Moderation
                │
        ┌───────┴────────┐
        │                │
        ▼                ▼
    FlowDrop            ECA
 multi-step work   bounded reactions
        │                │
        └───────┬────────┘
                ▼
        Drupal AI / Tools
                │
                ▼
      provider integrations

The system of record remains Drupal.

2. The Prime Engineering Law: Upstream First, Contrib First, Custom Last

DELETE DUPLICATION → DRUPAL CORE → EXISTING SECURITY-COVERED CONTRIB →
CONFIGURATION/SITE BUILDING → DRUPAL RECIPE → EXISTING CONTRIB EXTENSION POINT →
ECA/FLOWDROP → TOOL API/AI CONTEXT/MCP → EXISTING BLUEFLY OWNER →
CONTRIBUTE MISSING CAPABILITY UPSTREAM → THIN BLUEFLY ADAPTER →
CUSTOM SUBSYSTEM ONLY AFTER PROVEN GAP

This is stricter than "prefer contrib." A new Bluefly implementation is rejected when an accepted upstream layer already owns the concern. The goal is not better custom Drupal code — the goal is less Bluefly-owned Drupal code.

Drupal's AI Best Practices project now exists specifically as an upstream home for canonical Drupal guidance aimed at AI coding agents. It should be incorporated into the factory's Drupal engineering instructions rather than reproducing all Drupal coding knowledge in Bluefly prompts.

3. Current Platform Baseline — September 2, 2026

Version numbers are evidence, not doctrine. Before changing any dependency, agents must inspect the target site's current composer.lock, supported PHP version, Drupal core constraint, module compatibility, security coverage, and upgrade path.

Capability Upstream owner Current production posture
Drupal CMS Drupal CMS 2.1.x Required product base
Drupal Core Drupal 11.4.x Current production core line
Drupal 12 Drupal Core Prepare for it; do not pretend it has shipped
Site Templates Drupal CMS 2.1 Required AMCS product packaging mechanism
Canvas drupal/canvas:^1.10 Stable / security-covered
Drupal AI drupal/ai:^1.4 Stable / security-covered
AI Agents drupal/ai_agents:^1.3 Stable / security-covered
FlowDrop drupal/flowdrop:^2.5 Stable / security-covered
ECA drupal/eca:^3.1 Stable / security-covered
Modeler API drupal/modeler_api:^1.1 Stable / security-covered
Search API stable 1.x Stable search/index abstraction
Tool API drupal/tool:^1.0@beta Maturity-gated
Tool Belt drupal/tool_belt:^1.0@alpha Maturity-gated
Context Control Center drupal/ai_context:^1.0@beta Maturity-gated
MCP Server drupal/mcp_server:^2.0@beta Maturity-gated
Drupal CMS AI drupal/drupal_cms_ai 2.1.x Evaluated and not applied. The meta-recipe hard-requires ai_provider_amazeeio. Compose Drupal AI contrib on recipe_blucity instead.

Corrections from earlier architecture

Drupal 12. Drupal 12 has not shipped as of September 2, 2026. Drupal core's current release schedule now targets the week of December 7, 2026, alongside Drupal 11.5. Drupal 11 remains the production baseline. The architecture must be Drupal-12-ready, not Drupal-12-fictional.

FlowDrop. The old Bluefly guidance saying "FlowDrop 1.6 = production, FlowDrop 2.x = alpha, do not use" is obsolete. FlowDrop 2.5.0 is now a stable, Drupal Security Team-covered release for Drupal 11.3+. FlowDrop upstream describes workflows as Drupal configuration, provides persistent execution records, explicit graphs, human-in-the-loop, event triggers, nested workflows, Tool API integration, and AI-provider integration. The AMCS target should use the current supported FlowDrop 2.x line compatible with the site, not freeze itself on 1.6 because of an expired architectural assumption.

ECA. ECA's current line is 3.1.x for Drupal 11.3+ and Drupal 12. Modeling was extracted into Modeler API. The recommended editor is Workflow Modeler. Do not describe BPMN.io as the mandatory ECA architecture.

Tool API, Tool Belt, CCC, MCP. These are important upstream directions but are not all stable. They are intentionally maturity-gated. Their existence prevents Bluefly from inventing duplicate frameworks, but their maturity status must be respected before they become required production dependencies.

4. Drupal CMS Product Architecture

There are three Drupal product artifacts. They must remain distinct.

                    site_template_amcs
                    INSTALLABLE PRODUCT
                           │
             ┌─────────────┴─────────────┐
             ▼                           ▼
    recipe_blucity                recipe_amcs
       FOUNDATION                     DOMAIN

4.1 recipe_blucity

Repository: blueflyio/agent-platform/drupal/recipes/recipe_blucity

Purpose: reusable Drupal foundation shared by multiple Bluefly Drupal products.

May own: Drupal CMS foundation configuration; shared Drupal AI foundation composed from contrib (drupal/ai, ai_agents, ai_dashboard, ai_image_alt_text, canvas, provider modules except Amazee); Key integration structure; provider-neutral AI configuration; shared security defaults; shared roles where genuinely reusable; JSON:API defaults; Search API foundation; common audit/revision configuration; shared queue/scheduling configuration; common moderation primitives; shared Canvas/SDC infrastructure where product-neutral; accepted Tool API foundation if maturity-gated adoption has been approved. Must not require drupal/drupal_cms_ai or ai_provider_amazeeio.

Must not own: amcs_managed_article; AMCS-specific fields; AMCS QA states; AMCS QA FlowDrop workflows; AMCS-specific roles; AMCS compliance rules; AMCS agent definitions.

4.2 recipe_amcs

Repository: blueflyio/agent-platform/drupal/recipes/recipe_amcs

Purpose: reusable AMCS domain capability.

Owns: AMCS content model; AMCS fields; AMCS taxonomy requirements; AMCS moderation workflow; AMCS agent roles; AMCS human reviewer/publisher roles; AMCS permissions; AMCS FlowDrop workflows; bounded supporting ECA rules; AMCS AI Agent configuration; AMCS context configuration; QA result fields; compliance findings; runtime guardrails.

Dependency, confirmed at the source (composer.json, release/v0.1.x): recipe_amcs requires bluefly/recipe_blucity (^0.1.1 || dev-release/v0.1.x) directly. This is a real Composer-level edge, not an inferred one — recipe_blucity is the foundation recipe_amcs extends.

It is a Recipe, not the entire product. Once recipe_blucity provides ai / ai_agents, this recipe must not second-own them. Keep AMCS-specific FlowDrop, ECA, AI Context, Tool / Tool Belt, and ai_agents_ossa only where they are domain requirements.

AMCS-CF-001 (AMCS-CF-001.execution-packet.yml) is a certification / GovernedFact proof packet. It does not define the AMCS product.

4.3 site_template_amcs

Repository (GitLab path_with_namespace): blueflyio/agent-platform/drupal/site-templates/amcs/site_template_amcs. The shorter blueflyio/amcs/site_template_amcs string resolves to the same project id; commit URLs use the long path.

Purpose: installer-facing Drupal CMS product. Drupal CMS 2.1 provides first-class site-template selection and drush site:export, making this an actual upstream Drupal CMS product artifact rather than a Bluefly governance abstraction.

Owns: composition of recipe_blucity; composition of recipe_amcs; template metadata; preview image/screenshots; theme selection; Canvas product assembly; SDC/component selection; navigation; menus; dashboards; demonstration/default content; installer presentation; recommended optional Recipes.

It does not duplicate the configuration owned by either underlying Recipe. A Gas City Rig registration does not redefine this repository's purpose. Repository ownership determines product content. The Rig identifies where Gas City operates against that repository.

4.4 recipe_digital_service_baseline (sibling)

Repository: blueflyio/agent-platform/drupal/recipes/recipe_digital_service_baseline

This is a separate type: Site recipe. Do not nest, require, or apply it from recipe_amcs. It is not the AMCS product and not a substitute for site_template_amcs.

5. Drupal Product vs. Gas City Factory

This boundary is non-negotiable.

DRUPAL RECIPES + SITE TEMPLATES = PRODUCT ARTIFACTS

GAS CITY PACKS + FORMULAS + ORDERS + AGENTS = FACTORY BEHAVIOR

Gas City manufactures the Drupal product. Drupal runs the product. Product artifacts own configuration, permissions, moderation, AI integrations, layouts and runtime behavior; Gas City owns the method used to build, test, review, verify and release those artifacts.

Never put authoritative Drupal runtime configuration inside a Gas City Pack. Never put software-factory coordination inside a Drupal Recipe.

6. Gas City Upstream Ownership

Gas City should be used as Gas City, not approximated with Bluefly shell conventions. The upstream Pack model already provides reusable agents, formulas, orders, commands, doctor checks, skills, MCP configuration, named sessions, providers/runtimes, overlays, support assets.

A Pack is a directory with pack.toml; the Pack specification is the authoritative format contract.

Bluefly should not create another plugin loader, skill registry, Pack installer, NPM distribution convention, role registry, workflow scheduler, or custom agent lifecycle manager, unless the actual Gas City Pack surface cannot supply the capability.

Private Packs should use Gas City's durable import and credential-pointer mechanisms rather than embedding credentials in Pack URLs or inventing an authentication layer. The upstream model separates registry handle (local discovery), durable git source (committed import authority), packs.lock (exact resolved state), and cache (runtime materialization). Bluefly private imports may point at canonical GitLab sources and pin durable revisions. A Pack does not require NPM publication merely because it is reusable.

7. Gas City Primitive Ownership

Use the upstream meaning of each primitive:

Pack    = reusable configuration and behavior definitions
Rig     = registered project/work location
Agent   = executor identity/configuration
Formula = reusable method
Bead    = durable instantiated work
Order   = when work should be initiated
Gas City orchestrator = engine that advances the graph

Do not collapse them into one concept.

Formula ≠ work. A Formula describes a method, for example ship-amcs-product (establish authority → verify foundation → implement domain recipe → prove runtime → review → merge recipe → assemble site template → clean install → prove product → merge product → publish receipt). Cooking the Formula materializes real Beads. The Formula is reusable factory method; the Beads are the actual durable work.

The orchestrator — not an individual agent's memory — is responsible for advancing dependency gates, retries, fan-out, checks, and review loops. Gas City upstream describes this separation as: work = beads, method = formula, execution = orchestrator. Do not create an agent that manually recreates what a Formula and orchestrator already do.

8. Correct Beads / Dolt Topology

The previous mental model of "HQ database + separate rig databases + synchronization/import between them" must be retired.

Upstream Gas City defines the default city topology as:

ONE CITY → ONE SHARED DOLT SERVER
    ├── city issue_prefix
    ├── rig A issue_prefix
    ├── rig B issue_prefix
    └── rig N issue_prefix

Each City/Rig has its own .beads/config.yaml, but that does not imply a separate physical Dolt authority. For the normal topology: city gc.endpoint_origin = managed_city, rig gc.endpoint_origin = inherited_city. For an external Dolt topology, city_canonical and explicit are the additional legal endpoint-origin modes.

Each scope has an issue_prefix. bd enforces that prefix as a hard query filter. Therefore: same Dolt server ≠ same bd visibility. A bead belonging to iac-* may physically exist in the same Dolt store as an hq-* bead and still return "no issue found" when queried from the wrong scope. That is intentional isolation, not data loss.

gc bd --rig <name> is routing sugar: Gas City changes into the Rig directory and invokes bd. It is not a cross-Rig federation API. A true estate-wide view must query the shared Dolt authority appropriately rather than pretending bd list from the City root should aggregate every prefix.

Consequences for Bluefly: do not create separate Rig Dolt authorities to solve a visibility issue; do not import beads.json to rebuild normal work authority; do not treat JSONL exports as canonical work state; do not diagnose a prefix-filtered bd result as missing database rows; do not invent a Beads synchronization service; preserve one canonical City/Dolt authority unless upstream's explicit external topology requires otherwise.

Required tracked .beads/ files per the Beads Dolt Contract: config.yaml and metadata.json only (issue_prefix, gc.endpoint_origin, gc.endpoint_status, database, backend, dolt_mode, dolt_database). Dynamic runtime files (interactions.jsonl, metadata deltas, routes.jsonl) are gitignored, not committed. A blanket .beads/ gitignore that also sweeps config.yaml/metadata.json is a contract violation, not cleanup — verify per-repo before applying any .beads/-related .gitignore change.

9. Runtime Ownership Inside Drupal

Concern Owner
Content/business state Drupal entities/fields
Audit history of business state Drupal revisions
Editorial lifecycle Core Workflows + Content Moderation
Multi-step deterministic runtime workflow FlowDrop
Small event-condition-action automation ECA
Agent definition/tool selection AI Agents
Provider abstraction Drupal AI
Visual ECA modeling Modeler API + Workflow Modeler
Page/layout composition Canvas + SDC
Typed executable operations Tool API, when maturity accepted
Common operations Tool Belt, when maturity accepted
Governed AI context CCC/AI Context, when maturity accepted
Search/indexing Search API; AI Search when justified and verified
External tool protocol MCP Server, only where required
Deployment secret references Key / deployment secret authority
Recipe composition Drupal Recipes
Installable product composition Drupal CMS Site Template

This table is an ownership map, not a mandate to install every package.

10. Drupal AI Foundation

The default AI foundation is Drupal AI. All model/provider operations must pass through accepted Drupal AI provider plugins.

Bluefly must not create a new OpenAI client, new Anthropic client, new Bedrock client, new Gemini client, new LiteLLM client, new generic LLM service, or new provider registry merely because an application requires AI. Provider-specific modules own vendor connectivity. Drupal AI owns provider-neutral operations. The Recipe should express the capability, not a credential.

Deployment/runtime configuration supplies credentials, endpoint URLs, organization/project IDs, model aliases, customer-specific provider selection. Do not put an Anthropic/OpenAI/LiteLLM endpoint or credential in recipe_amcs.

Drupal CMS's own AI recipe (drupal/drupal_cms_ai) already installs AI Core, AI Agents, AI Dashboard, AI Image Alt Text, provider modules, Key and Canvas integration. That was the first foundation evaluated. Do not apply it: the meta-recipe hard-requires ai_provider_amazeeio. recipe_blucity composes the equivalent contrib modules without Amazee. recipe_amcs consumes that foundation and must not duplicate ai / ai_agents once they arrive from recipe_blucity.

11. AI Agents

AI Agents owns configurable Drupal-native agents. Use it for agents that create or improve draft content; suggest taxonomy; perform metadata analysis; perform editorial analysis; perform compliance review; inspect site state; invoke bounded Tools.

Agent logic does not own the publication state machine. An AI Agent may determine "this article passes QA" but the durable result must become governed Drupal state through an authorized workflow/tool operation. The agent itself must not bypass Content Moderation and directly publish content.

12. Content Moderation: The Authority for Publication

Core Drupal Content Moderation owns the AMCS publication lifecycle.

draft → agent_qa → (fail) → needs_revision
              │
           (pass) → human_review → (authorized HUMAN) → published → archived

The important rule is not the exact label. It is: no autonomous agent receives the permission needed to publish production content.

Agent identities can be allowed to create drafts; revise permitted content; populate QA fields; attach findings; move content into an agent-owned QA stage; return failed work to revision; recommend or perform an allowed transition to human_review.

Only the explicitly authorized human publishing role transitions content to published. This is enforced by Drupal permissions/workflow transition access — not by trusting an agent prompt.

13. FlowDrop: Multi-Step Runtime Workflow Owner

FlowDrop is the primary owner for the AMCS editorial QA pipeline. Do not recreate it with a custom queue service; a PHP state machine; a custom agent orchestration loop; an ECA graph duplicating the same pipeline; a Gas City Formula; or a remote automation tool.

FlowDrop upstream now provides explicit typed graph edges; Drupal configuration-backed workflows; execution records; synchronous/asynchronous/resumable execution; human-in-the-loop pauses; entity operations; branching; nested workflows; event triggers; AI-provider integration; Tool API integration; persistent execution lineage.

The AMCS workflow should therefore be:

CONTENT ENTERS agent_qa → LOAD CURRENT REVISION → VERIFY ENTRY GUARDS
  → DETERMINISTIC VALIDATION (required fields, media requirements, references,
    taxonomy, accessibility signals, link validation where available)
  → OPTIONAL GOVERNED AI ANALYSIS (style-guide alignment, compliance language,
    unsupported-claim analysis, summary quality, taxonomy/content recommendations)
  → AGGREGATE FINDINGS → BRANCH
       FAIL → needs_revision
       PASS → human_review
  → UNPUBLISHED

An LLM is a node/tool inside the workflow. It is not the workflow engine.

14. Required AMCS FlowDrop Guards

The workflow must have deterministic entry protection. At minimum: entity type = node; bundle = amcs_managed_article; moderation state = agent_qa; QA state = pending/unprocessed; current revision not previously processed.

The workflow must not trigger again when its own mutations cause a subsequent entity save. Guard against needs_revision, human_review, published, archived, QA fail, QA pass, an already-processed revision, unrelated bundles.

Acceptance: one qualifying revision → exactly one QA execution → zero recursive executions. Do not declare recursion solved from static graph inspection alone. Prove it with runtime execution records.

15. ECA: Bounded Automation, Not Duplicate Workflow

ECA remains a major Drupal automation framework. It should own the smaller deterministic reactions around the AMCS lifecycle: initialize a QA status; set an initial deadline; add a compliance tag; notify a reviewer; schedule follow-up work; react to entity lifecycle events; enqueue bounded work; react when a Recipe is applied.

Do not duplicate the FlowDrop QA graph in ECA. The rule is: multi-step pipeline with explicit data flow → FlowDrop; small event-condition-action reaction → ECA.

Existing AMCS ECA logic that duplicates FlowDrop should not be deleted until FlowDrop exported + clean installed + failure path proven + success path proven + recursion proven zero. Then remove the duplicate owner.

16. Modeler API and Workflow Modeler

Modeler API owns generic model lifecycle and modeler integration. It does not become another workflow engine. For ECA, current upstream recommends Workflow Modeler.

ECA           = model owner / automation engine
Modeler API   = model lifecycle and modeler abstraction
Workflow Modeler = recommended authoring interface

Do not describe BPMN.io as the required platform architecture. Use another modeler only when a concrete use case justifies it.

17. Tool API: Typed Execution Contract

Tool API is the direction for typed, reusable Drupal operations. It currently remains beta and therefore requires an explicit maturity gate. When accepted, use it instead of hand-building arbitrary agent actions.

A Tool should represent one bounded operation with typed input; typed output; validation; clear permissions/access semantics; a narrow responsibility; no hidden provider coupling.

Potential AMCS examples: load_current_article, record_qa_findings, request_human_review, retrieve_governed_context, inspect_revision.

Do not automatically write those plugins. First check Tool Belt, FlowDrop built-in nodes, Drupal core operations, existing contrib Tool collections, and the target module's own tools. Custom Tool code is still custom code. Typed custom code is not automatically justified custom code.

18. Tool Belt

Tool Belt exists specifically to prevent projects from rewriting common entity/user/workspace operations. Current upstream tools include operations for loading entities; listing entities; reading fields; setting fields; adding revisions; saving entities; adding/modifying entity bundles and fields; user role operations; workspace creation/switching/publishing; workspace preview. It is currently alpha.

Therefore: existence means do not reimplement blindly; alpha maturity means do not make it a production requirement blindly. Audit the specific required submodule and operation. Pin and test it when adopted.

19. Context and "Memory"

The original architecture jumped too quickly from "we need governed organizational memory" to "we need kb_cache + custom memory tools + VectorBridge." That is no longer acceptable.

Default ownership order:

Drupal content/entity state → AI Context / Context Control Center → Search API /
accepted AI Search path → existing Bluefly module → thin extension →
custom subsystem only after proven gap

Context Control Center already provides a Drupal-native direction for storing organizational context as governed content with revisions; moderation; scheduling; scopes; language/site section/target/use-case targeting; agent context consumption. It is currently beta. Adopt it behind a maturity gate. Do not turn its beta status into permission to create a competing permanent context architecture.

kb_cache is not automatically part of the target architecture. It must be audited. For every feature inside it classify as one of: DELETE, REPLACE_WITH_CORE, REPLACE_WITH_CONTRIB, CONFIGURE_CCC, CONFIGURE_SEARCH_API, KEEP_EXISTING_BLUEFLY_OWNER, THIN_ADAPTER_REQUIRED, PROVEN_CUSTOM_GAP. Do not assume a custom agent_memory entity/bundle implementation is required merely because one was designed previously. If CCC's supported content model can represent the requirement through configuration, use it. If normal Drupal content entities are the correct business authority, use them. If a new CCC scope plugin is all that is missing, write only the scope plugin.

No VectorBridge by default. Do not create a custom VectorBridge service unless: (1) Search API has been evaluated; (2) AI Search has been evaluated for the installed Drupal AI version; (3) accepted VDB provider modules have been evaluated; (4) access-control behavior has been tested; (5) none exposes the required operation; (6) the missing operation cannot reasonably be contributed upstream. The vector index is an index. Drupal remains authority.

20. Search and RAG

Search API is the stable Drupal search/index abstraction. RAG architecture should begin with:

Drupal entities → Search API → accepted backend / VDB provider →
AI Search where compatible and accepted → governed retrieval

Do not create a parallel RAG database and then declare it authoritative. Retrieval must preserve Drupal access rules. A returned vector/chunk must not become an access-control bypass. If the underlying result cannot be tied back to a Drupal entity for access checking, that risk must be explicitly accepted or the index itself must enforce equivalent restrictions.

21. External Agent Access and MCP

MCP is an edge protocol. It does not own business logic. MCP Server is currently beta. Use it only when external agents actually require governed Drupal Tool access.

Claude / Cursor / external agent → OAuth / identity → MCP Server →
approved Tool → Drupal access check → Drupal entity / workflow operation

Do not expose unrestricted entity mutation. Do not create custom REST endpoints merely to reproduce Tool/MCP capabilities. Do not make MCP a second application layer. If the product does not require external MCP access, it does not need MCP merely because MCP exists.

22. Canvas and SDC

Canvas owns visual page composition. Single Directory Components own reusable Drupal component implementation. site_template_amcs should assemble the product's Canvas/SDC experience.

Agents may participate in page construction through accepted Canvas/AI surfaces, but generated layout state remains Drupal state. The governance question is not "can an agent generate a page?" It is "what state does generation create, who may approve it, and can any automated path make unreviewed content public?" Canvas AI auto-save, revisions, moderation interaction, and Workspace behavior must be tested as real runtime behavior. Do not infer human-in-the-loop safety from the existence of Content Moderation alone.

23. Agent Identities and Least Privilege

Production agents require explicit identities and least-privilege roles. Example role classes: amcs_agent_author, amcs_agent_editorial_qa, amcs_agent_taxonomy, amcs_agent_compliance, amcs_agent_maintenance, amcs_human_reviewer, amcs_human_publisher. Exact names should come from the Recipe.

An agent role may receive only the permissions needed for its responsibility. Agent roles generally may: create draft revisions; edit explicitly authorized fields; read relevant governed context; execute approved Tools; add QA findings; request allowed transitions.

Agent roles must not receive broad permissions to: publish; administer users; administer permissions; administer modules; modify workflow configuration; alter AI provider configuration; bypass field/entity access; execute arbitrary PHP; use unrestricted administrative Tools.

The human publisher role owns publication. This is enforced technically. It is not prompt policy.

24. Credentials and Provider Configuration

Recipes and Site Templates must not contain credentials. Do not export API keys; OAuth secrets; PATs; provider passwords; private endpoints containing embedded credentials.

Drupal Key and deployment secret mechanisms should be used as appropriate. The Recipe may declare configuration structure and key references where supported. The deployment supplies actual secret material. Do not build a Bluefly secret store inside Drupal.

25. Proof and Audit

The original architecture prematurely mandated a Bluefly append-only SHA-256 chain + Merkle roots + ContractPlane as though those mechanisms were required for every governed Drupal deployment. They are not part of the default AMCS baseline.

Start with the proof surfaces Drupal and contrib already provide: Drupal revisions; Content Moderation history; FlowDrop execution records; human approval records; AI operation/logging/observability; Drupal logs; Git source history; GitLab CI/release evidence. These establish substantial provenance without another ledger.

ContractPlane may remain a Bluefly external proof/evidence system where a product or customer requirement justifies it. It must not replace Drupal entity access; Drupal permissions; moderation transition access; FlowDrop runtime state; GitLab release evidence.

Cedar may be used as an additional external/ABAC policy layer when a concrete requirement requires it and its integration owner has been established. Do not make Cedar a prerequisite for basic Drupal authorization. Do not write a second access-control system merely because Cedar exists. Drupal access checks still apply.

Hash chains / Merkle proofs. Implement cryptographic append-only proof only when a regulatory requirement, customer contract, or explicit platform proof requirement demands stronger tamper-evidence than existing Drupal/Git/GitLab/FlowDrop records provide. That requirement must be demonstrated first. No generic HashChainService merely because immutable audit sounds desirable.

26. OSSA and DUADP

OSSA/DUADP may remain Bluefly interoperability protocols for portable agent identity, discovery, or manifests. They are not Drupal's content authority. An external identity may map to a Drupal service identity or role.

external agent identity / manifest → authentication / mapping →
Drupal user/service identity → Drupal role + permissions → Tool/workflow authorization

The manifest describes the agent. It does not grant itself permissions. If OSSA/DUADP integration requires custom Drupal code, first inspect AI Agents extension points; configuration entities; Tool API; OAuth/authentication extension points; MCP identity/access integration; existing Bluefly owner. Only the missing adapter belongs to Bluefly.

27. Existing Bluefly Modules Are Candidates, Not Sacred Architecture

Existing private/custom modules must be audited against upstream continuously. Examples include kb_cache, kb_cache_ccc, contextcontrol_data, ai_agents_agui, ai_agents_agui_bridge, contractplane_client, api_normalization, source_connector, duadp, cedar_policy, mcp_client, mcp_registry, mcp_gateway, custom dashboards.

The fact that code exists does not prove it should continue to exist. Each receives one decision: REUSE, REDUCE, PATCH, MOVE_TO_RECIPE, REPLACE_WITH_CONTRIB, CONTRIBUTE_UPSTREAM, DEPRECATE, DELETE, BLOCKED_PENDING_EVIDENCE. The desired trajectory is net-negative custom ownership.

28. Explicit Custom-Code Deletion Candidates

The following patterns are rejected unless a demonstrated gap exists.

Existing/custom pattern Upstream-first target
Direct provider clients Drupal AI + provider modules
Custom agent loop AI Agents / FlowDrop depending responsibility
Custom workflow engine FlowDrop or ECA
Custom event subscriber glue ECA where supported
Custom entity CRUD agent wrappers Tool Belt / FlowDrop / Drupal APIs
Custom context entity system CCC or normal Drupal content model
Custom vector search abstraction Search API / AI Search / VDB provider
Custom MCP implementation MCP Server
Config-only module Recipe
Custom publish state Content Moderation
Duplicate agent permissions engine Drupal permissions/access
Custom AI provider credential store Key / deployment secrets
Bespoke page component framework Canvas + SDC
Separate audit DB for normal workflow lineage revisions + FlowDrop execution records
Manual release procedure repeated by agents Gas City Formula
Custom scheduler/watchdog for factory work Gas City Order
Separate Rig work DB shared City Dolt + prefix-scoped Beads

29. AMCS Required Business State

The exact field contract is owned by recipe_amcs. Do not invent field names in an architecture document and then force the implementation to conform to them.

The Recipe should contain whatever fields are actually required for durable AMCS business state, such as the conceptual categories: QA state; QA findings; last QA execution reference; agent actor/provenance; AI provider/model metadata when required; confidence when meaningful; review deadline; compliance tags; source references.

The implementation agent must read the committed Recipe and produce the exact field contract: machine_name, field_type, Drupal required?, QA required?, valid empty behavior, validation rule, deterministic failure message, business owner.

FlowDrop execution data provides operational lineage. Drupal entity fields/revisions provide durable business state. Do not duplicate the same state in a second custom database.

30. AMCS Required Runtime Vertical

The first product vertical is intentionally narrow:

AMCS ARTICLE → DRAFT → AGENT_QA → FLOWDROP → DETERMINISTIC CHECKS →
OPTIONAL GOVERNED AI CHECKS → FAIL/PASS → NEEDS_REVISION / HUMAN_REVIEW →
HUMAN ONLY PUBLISH

This is the baseline capability. Do not delay it while designing a generalized agent memory system; a universal policy fabric; a custom proof ledger; a Gas City factory redesign; an MCP platform; a new Pack; a new Bluefly module.

First ship one correct vertical. Then generalize only what repeats.

31. Acceptance Test — Failure Path

Create a real incomplete amcs_managed_article revision. Transition it through the supported moderation path into agent_qa. Prove:

FLOWDROP_EXECUTIONS=1
BRANCH=FAIL
QA_STATUS=FAIL
FINDINGS=DETERMINISTIC_AND_SPECIFIC
MODERATION_STATE=needs_revision
PUBLISHED=NO
RECURSION=0
AGENT_IDENTITY_RECORDED=YES

A result such as "QA failed" is insufficient. The findings must identify the actual failing requirements.

32. Acceptance Test — Success Path

Create a separate complete article satisfying the field contract. Transition it into agent_qa. Prove:

FLOWDROP_EXECUTIONS=1
BRANCH=PASS
QA_STATUS=PASS
FINDINGS=CLEARED_OR_CORRECT
MODERATION_STATE=human_review
PUBLISHED=NO
RECURSION=0
AGENT_IDENTITY_RECORDED=YES

Then separately prove: AGENT_CAN_PUBLISH=NO, AUTHORIZED_HUMAN_CAN_PUBLISH=YES. The successful QA result does not itself publish the article.

33. Clean Installation Is Part of the Feature

A DDEV database is not source authority. No valid product milestone may live only in MariaDB.

For every meaningful configuration milestone: configure through supported Drupal/contrib surface → verify runtime → export configuration → place in correct Recipe/product owner → validate → commit → push.

The Recipe is not accepted because the development database works. Acceptance requires: fresh code checkout → Composer install → Drupal install → apply recipe_blucity → apply recipe_amcs → no manual FlowDrop repair → execute failure fixture → execute success fixture.

Then the Site Template must independently prove: fresh Drupal CMS installation → choose/apply site_template_amcs → both Recipes applied → Canvas/theme/product configuration available → failure path passes → success path passes → human publication boundary passes.

34. Drupal CMS Site Template Delivery

After recipe_amcs is independently merged and verified, site_template_amcs assembles the complete product.

Drupal CMS 2.1.x → site_template_amcs (recipe_blucity + recipe_amcs)
  + theme + Canvas + SDC components + navigation + dashboards + demonstration content

The Site Template should use current Drupal CMS site-template mechanisms. It must not become a repository that merely contains instructions about another imaginary Site Template.

Customer #2 portability is an acceptance test, not a second product: a second independently created customer-shaped site from the same site_template_amcs, without Bluefly-specific copies. bluefly.io is a later reference consumer. AMCS ≠ bluefly.io.

35. Factory Implementation

Once the Drupal product delivery method is proven, repeatable engineering procedure belongs in a Gas City Pack/Formula.

A reasonable reusable Pack composition:

drupal-factory
  ├── recipe engineer, site-template engineer, contrib auditor,
  │   config verifier, security reviewer, release steward
  ├── Drupal Recipe skills, contrib-first skill, config-first skill,
  │   clean-install proof
  └── doctor checks

AMCS-specific factory behavior may extend it with a workflow reviewer, governance reviewer, runtime verifier, and a ship-amcs-product Formula.

The AMCS product does not wait for a factory refactor. If the Pack/Formula does not exist today, record that reusable-method gap and continue shipping the actual Drupal artifact. Once a delivery method repeats, encode it upstream in the factory owner.

36. Factory Formula for the Mature Delivery Path

After the path has been proven manually once through canonical tooling, an AMCS Formula should eventually resemble:

ship-amcs-product
├── establish-authority
├── audit-upstream (Drupal core, Drupal contrib, installed estate)
├── implement-domain-recipe
├── export-config
├── clean-install-domain-recipe
├── runtime-proof (failure-path, success-path, permission-boundary)
├── review (contrib-first, duplicate-code, security, configuration, runtime evidence)
├── merge-domain-recipe
├── assemble-site-template
├── clean-install-site-template
├── repeat-runtime-proof
├── merge-site-template
└── final-receipt

The Formula describes factory work. It does not become the deployed Drupal content workflow.

37. FlowDrop ≠ Gas City Formula

GAS CITY FORMULA = HOW SOFTWARE IS MANUFACTURED
FLOWDROP WORKFLOW = HOW THE INSTALLED DRUPAL PRODUCT EXECUTES BUSINESS PROCESS

Gas City example: implement → test → review → fix → merge → assemble → verify → release. FlowDrop example: content enters QA → validate → AI analysis → branch → write findings → moderation transition → human approval.

Never use Gas City as the Drupal site's editorial runtime. Never use FlowDrop as the software factory.

38. Two Agent Systems

There are two different meanings of "agent."

Gas City factory agents operate against software projects. They may inspect repositories, edit source, run DDEV, apply Recipes, export config, test, review, commit, push, open MRs, consume CI, verify releases.

Drupal runtime agents operate through the installed Drupal application. They may draft content, analyze content, classify, suggest taxonomy, perform QA, retrieve governed context, invoke approved Tools, perform bounded maintenance.

A Gas City Agent definition does not automatically become a Drupal AI Agent. A Drupal AI Agent does not automatically gain repository access. Keep the identities and authority models separate.

39. Source, Checkout, Runtime, and Work Authority

Do not conflate physical filesystem location with authority.

GitLab                          = versioned source authority
NAS                              = shared checkout / durable storage
Mac worktree                     = bounded engineering transaction
Gas City                         = factory runtime/orchestration
Dolt / Beads                     = durable engineering work graph
Drupal database                  = installed application state
Drupal Recipe / Site Template in Git = reproducible product definition

A local DDEV database cannot become the only copy of product configuration. A NAS clone cannot become version authority. A .beads/issues.jsonl file cannot become work authority. A Gas City Rig does not redefine repository ownership.

40. Security and Governance Rules

Publication:
  AGENT_PUBLISH_PERMISSION=DENIED
  HUMAN_PUBLISH_PERMISSION=EXPLICIT

Secrets:
  SECRETS_IN_RECIPE=NO
  SECRETS_IN_SITE_TEMPLATE=NO
  SECRETS_IN_PACK_URL=NO
  SECRETS_IN_GIT_REMOTE=NO
  SECRETS_PRINTED=NO

Provider isolation:
  DIRECT_LLM_SDK_FROM_CUSTOM_DRUPAL_CODE=NO

Workflow ownership:
  DUPLICATE_ECA_AND_FLOWDROP_PIPELINE=NO
  CUSTOM_WORKFLOW_ENGINE=NO

Data authority:
  CUSTOM_PARALLEL_CONTENT_STORE=NO
  VECTOR_INDEX_AS_AUTHORITY=NO

Factory:
  CUSTOM_BEADS_SYNC=NO
  CUSTOM_PACK_REGISTRY_BEFORE_UPSTREAM=NO
  CUSTOM_AGENT_LIFECYCLE_BEFORE_GAS_CITY=NO

41. Custom Code Gap Receipt

Before any new Bluefly PHP implementation is accepted, produce:

CUSTOM_CODE_GAP_RECEIPT:
  requested_capability:
  drupal_core_checked:
  contrib_projects_checked: []
  existing_recipes_checked: []
  eca_capabilities_checked: []
  flowdrop_capabilities_checked: []
  tool_api_checked:
  tool_belt_checked:
  ai_context_checked:
  existing_bluefly_owners_checked: []
  closest_upstream_owner:
  missing_capability:
  upstream_issue_or_extension_path:
  why_configuration_is_insufficient:
  why_recipe_is_insufficient:
  why_existing_extension_point_is_insufficient:
  proposed_custom_surface:
  expected_lines_or_components:
  removal_condition:
  upstream_contribution_required:
  authorized_by:

No receipt: no new custom subsystem. If upstream is close but missing one extension point, first preference is to contribute the extension upstream and consume it — not fork forever.

42. Current hq-b1m Delivery Directive

The immediate product work remains bounded.

Bead: hq-b1m
Rig: amcs-recipe
Repository: blueflyio/agent-platform/drupal/recipes/recipe_amcs

Mission: ship the real AMCS domain Recipe. Do not redesign the factory. Do not create new Pack infrastructure. Do not move AMCS behavior into recipe_blucity. Do not start with a custom module. Do not stop at tests.

Required execution: 1. Establish current branch/MR/source authority 2. Preserve valid DDEV state 3. Inspect current Composer lock 4. Re-verify upstream capability against installed versions 5. Establish exact AMCS field contract 6. Establish Content Moderation states/transitions 7. Use current supported FlowDrop 2.x APIs/configuration 8. Build the actual QA workflow 9. Export workflow/configuration 10. Prove incomplete-content path 11. Prove complete-content path 12. Prove zero recursion 13. Prove agent cannot publish 14. Prove human publisher can publish 15. Remove superseded duplicate ECA gate 16. Clean-install recipe from Git 17. Repeat runtime proofs 18. Commit 19. Push 20. MR to release/v0.1.x 21. CI 22. Merge 23. Verify merge SHA 24. Route site-template assembly 25. Clean-install site template 26. Repeat runtime proofs 27. Merge site-template 28. Close proven Beads 29. Remove bounded worktrees safely

Do not stop after: architecture understood, config written, tests written, commit pushed, MR opened. The terminal is shipped runtime capability.

43. Required Runtime Receipt

GOVERNED_DRUPAL_AMCS_RECEIPT

SOURCE HIERARCHY
  Upstream Drupal Checked:
  Upstream Gas City Checked:
  Installed Composer Lock Checked:

PLATFORM
  Drupal CMS: / Drupal Core: / Canvas: / Drupal AI: / AI Agents: /
  FlowDrop: / ECA: / Modeler API: / Search API:

MATURITY-GATED
  Tool API: / Tool Belt: / AI Context: / MCP Server:

PRODUCT OWNERS
  recipe_blucity: / recipe_amcs: / site_template_amcs:

FACTORY
  City: / Rig: / Pack Binding: / Formula: / Bead: /
  Dolt Endpoint Origin: / Issue Prefix:

CUSTOM OWNERSHIP
  Existing Bluefly Modules Used: / Bluefly Modules Reduced: /
  Bluefly Modules Deleted: / Custom PHP Added: /
  Custom Tool Plugins Added: / Custom Services Added: / Gap Receipts:

WORKFLOW
  Moderation Workflow: / FlowDrop Workflow: / Entry Trigger: / Entry Guards: /
  Failure Branch: / Success Branch: / Recursion Guard: /
  Old Duplicate ECA Gate Removed:

FAILURE PROOF
  Node: / Revision: / Execution: / Execution Count: / QA Status: /
  Findings: / Moderation State: / Published: / Recursion:

SUCCESS PROOF
  Node: / Revision: / Execution: / Execution Count: / QA Status: /
  Findings: / Moderation State: / Published: / Recursion:

AUTHORITY PROOF
  Agent Publish Denied: / Human Publisher Publish Proven:

PRODUCT PROOF
  Recipe Config Export: / Recipe Clean Install: /
  Recipe Runtime Failure Proof: / Recipe Runtime Success Proof: /
  Site Template Clean Install: / Site Template Runtime Failure Proof: /
  Site Template Runtime Success Proof:

DELIVERY
  recipe_amcs Commit: / recipe_amcs MR: / recipe_amcs CI: / recipe_amcs Merge SHA:
  site_template_amcs Commit: / site_template_amcs MR: /
  site_template_amcs CI: / site_template_amcs Merge SHA:

WORK
  Child Beads Closed: / Root Bead Closed: / Unpushed Source: / Abandoned Worktrees:

FINAL: COMPLETE | VERIFIED_UPSTREAM_GAP | BLOCKED_BY_SPECIFIC_EXTERNAL_AUTHORITY

44. What This Architecture Explicitly Rejects

The Governed Drupal CMS is not: a custom Drupal AI framework; a custom provider abstraction; a custom agent runtime; a custom workflow engine; a custom RAG framework; a custom context database; a custom permissions engine; a custom MCP implementation; an app whose business state lives in Gas City; a Gas City workflow disguised as an editorial workflow; an ECA graph duplicating a FlowDrop graph; a pile of PHP services wrapped in a Recipe; an architecture document whose invented components become requirements merely because they were diagrammed.

The architecture is deliberately smaller than previous versions. That is progress.

45. Final Reference Architecture

                           BLUEFLY SOFTWARE FACTORY

                                  GitLab
                        versioned source authority
                                    │
                                    ▼
                               GAS CITY
                                    │
                 ┌──────────────────┼──────────────────┐
                 │                  │                  │
               Packs             Formulas            Orders
           reusable factory    reusable method      when to run
                 │                  │
                 └──────────┬───────┘
                            ▼
                    materialized Beads
                            │
                  ONE SHARED DOLT AUTHORITY
                 prefix-scoped City / Rigs
                            │
             ┌──────────────┼────────────────┐
             ▼              ▼                ▼
    recipe_blucity   recipe_amcs   site_template_amcs
       FOUNDATION         DOMAIN           PRODUCT
             │              │                │
             └──────────────┴────────────────┘
                            │
                            ▼
                  INSTALLABLE DRUPAL CMS
                            │
          ┌─────────────────┼─────────────────┐
          │                 │                 │
          ▼                 ▼                 ▼
      Drupal Core         Canvas          Drupal AI
 Entities / Revisions    + SDC          + AI Agents
 Permissions / Access                      │
 Content Moderation                        │
          │                                 │
          └──────────────┬──────────────────┘
                         ▼
                GOVERNED EXECUTION
                         │
                  ┌──────┴──────┐
                  ▼             ▼
              FlowDrop          ECA
           multi-step graph   bounded E/C/A
                  │             │
                  └──────┬──────┘
                         ▼
                accepted Tool layer
                 where maturity allows
                         │
              ┌──────────┼───────────┐
              ▼          ▼           ▼
          AI Context  Search API     MCP
           context      index       edge
              │          │           │
              └──────────┴───────────┘
                         │
                         ▼
                 DRUPAL SYSTEM OF RECORD
                         │
             ┌───────────┴───────────┐
             ▼                       ▼
       GOVERNED AGENTS             HUMANS
       bounded actions        final authority where
                              policy requires humans

The core sentence is: Gas City manufactures the Drupal product; Drupal runs and governs the product. Packs encode reusable factory behavior, Formulas encode method, Beads represent durable work in a shared prefix-scoped Dolt authority, Recipes encode reusable Drupal capability, and Drupal CMS Site Templates assemble the installable product. Agents operate through Drupal's existing authority instead of becoming a second authority.

The engineering test for every new line remains: does Drupal Core, accepted contrib, configuration, a Recipe, ECA, FlowDrop, Tool API, AI Context, an existing Bluefly owner, Gas City, or Beads already own this concern? If yes: use the owner. Do not own another implementation.