Skip to content

STD-DRUPAL-004: Producer / Consumer Repository Ownership

Status: Active Authority: Bluefly Engineering — Drupal Architecture Date: 2026-10-10


0. Estate Rule (Canonical Language)

PRODUCER REPO OWNS SOURCE.
CONSUMER SITE OWNS COMPOSITION.
WEB TREE IS NOT AUTHORITY.
NO ORPHANED SOURCE CHANGES.

These four statements are binding across the entire Bluefly Drupal estate.


1. Scope

This standard applies to every Bluefly-owned Drupal package type:

Package type Ownership model
Custom module Own canonical repository
Custom theme Own canonical repository
Recipe Own canonical repository
Site template Own canonical repository
DDEV add-on Own canonical repository
Canvas/SDC producer Own canonical repository
Private extension Own canonical repository
Other Drupal package Own canonical repository

A Drupal site (bluefly.io, contextcontrol-ai, etc.) is a consumer. It assembles producer packages through Composer. It does not own their source.


2. Producer vs Consumer Responsibilities

2.1 Producer repo owns

PHP source
Twig templates
JavaScript
CSS / SCSS
SDC component definitions (.component.yml, .twig, scoped assets)
Module / theme metadata (.info.yml, .libraries.yml, .services.yml)
Services and plugins
Tests (PHPUnit, Nightwatch, Kernel, etc.)
Package-level CI (.gitlab-ci.yml or CI component inclusion)
Recipe definitions
Site-template definitions

2.2 Consumer site may own

composer.json
composer.lock
config/sync/
Site-specific Canvas page composition (canvas_page entities)
Site-specific content and configuration
settings.php / settings.local.php
DDEV consumer configuration (.ddev/)
Deployment configuration (docker-compose, Terraform, Cloudflare)
Site-specific integration configuration

2.3 The distinction

COMPONENT DEFINITION → PRODUCER
PAGE COMPOSITION     → CONSUMER

A producer defines a reusable SDC component (cc-hero, bluefly-button). A consumer places that component on a Canvas page with specific prop values.


3. Filesystem Location Does Not Define Authority

A writable file under web/ is never evidence of ownership. Repository and package ownership defines authority.

3.1 Embedded .git does not grant authoring authority

A package checkout located under a consumer site at:

web/modules/custom/<package>/
web/themes/custom/<package>/

may be any of:

  • Composer source-install projection
  • Embedded producer checkout (local cache)
  • Runtime clone

Regardless of whether it contains its own .git directory, it is classified as:

CONSUMER_RUNTIME_PROJECTION
READ_ONLY_FOR_AGENT_AUTHORING

until proven to be a Gas City governed worktree of the producer Rig.

3.2 Rule

EMBEDDED .git ≠ DEVELOPMENT AUTHORIZATION

An embedded .git proves the path is a separate repository. It does not prove the path is an approved development worktree.


4. Required Pre-Edit Gate

Before any agent edits Drupal producer source, the agent must determine:

WHAT_PACKAGE=
WHAT_PROJECT_TYPE= (module | theme | recipe | site-template | ddev-addon | other)
WHAT_GITLAB_REPO=
WHAT_RIG=
WHAT_BEAD=
IS_GOVERNED_WORKTREE= YES | NO

If IS_GOVERNED_WORKTREE is not YES:

DO_NOT_EDIT

The agent must instead:

  1. Identify the producer repository
  2. Obtain or create a governed worktree for the producer Rig
  3. Branch from current release/v0.1.x
  4. Perform edits in the governed worktree
  5. Follow the delivery flow (§5)

5. Required Delivery Flow

The canonical producer-to-consumer lifecycle:

Bead
→ Producer Rig
→ Governed producer worktree
→ Feature branch from release/v0.1.x
→ Implementation
→ Producer tests
→ Commit (approved identity only)
→ Push
→ Producer MR → release/v0.1.x
→ CI (PASS required)
→ WITNESS (PASS required)
→ Merge

→ Consumer site: composer update <package>
→ Consumer: composer.lock updated
→ Consumer MR → release/v0.1.x
→ CI (PASS required)
→ Visual/runtime verification
→ WITNESS (PASS required)
→ Merge

The following is explicitly prohibited:

ANTI-PATTERN:
  edit installed copy under web/
  → site looks correct locally
  → producer repo unchanged
  → next composer install destroys the change

6. Orphaned Source Changes

6.1 Definition

An orphaned source change is a legitimate producer-source modification found only inside a consumer/runtime checkout — never committed to the producer repository.

6.2 Recovery procedure

1. Preserve the exact diff
2. Identify the owning producer repository
3. Identify the existing Bead (or create one if none exists)
4. Recover the diff into a governed producer worktree
5. Deliver a producer MR through the standard flow (§5)
6. Merge the producer change
7. Update the consumer via Composer
8. Clean the consumer projection

6.3 Rules

  • Never delete valid unique work merely to make the consumer repository clean.
  • Never use committed .patch files as a substitute for recovering source into its producer repository.
  • Target: ORPHANED_PRODUCER_CHANGES=0

7. Prohibited Git Operations

Agents must not use the following as generic recovery or development techniques inside consumer sites:

git add -f web/modules/custom/...
git add -f web/themes/custom/...
git clean -fd        (without per-path classification first)
git commit --no-verify

git clean requires every affected untracked path to be classified as: owned by this repo, owned by a producer, or generated artifact — before removal.


8. Configuration Safety

Before every Drupal config import or export:

ddev drush cst

Record the result. Do not blanket export configuration.

CST_BEFORE=
CONFIG_DIRECTION= (import | export)
CST_AFTER=
LATEST_CONFIG_IN_GIT=YES

9. Gas City Alignment

This standard reinforces the execution model:

Concern Authority
Orchestration / work Gas City
Durable work tracking Beads
Project execution scope Rig
Source / MR / CI / release GitLab
Execution surface DDEV (local) / Oracle (production)

Drupal sites do not become work authorities, schedulers, or Bead stores.


10. Bluefly Estate Examples

10.1 Correct ownership map

Package Producer repository (GitLab)
bluefly_theme blueflyio/agent-platform/drupal/themes/bluefly_theme
contextcontrol_theme blueflyio/agent-platform/drupal/themes/contextcontrol_theme
contractplane_client blueflyio/agent-platform/drupal/private/contractplane_client
source_connector blueflyio/agent-platform/drupal/private/source_connector
recipe_blucity blueflyio/agent-platform/drupal/recipes/recipe_blucity
agentic_canvas blueflyio/agent-platform/drupal/themes/agentic_canvas

10.2 Correct workflow

# Producer: fix a bug in bluefly_theme
bead → bluefly_theme rig → governed worktree
→ git checkout -b fix/<bead>-description
→ edit src/tokens.css
→ npm run build
→ git commit
→ git push
→ MR to release/v0.1.x
→ CI PASS → WITNESS PASS → merge

# Consumer: pull the fix into bluefly.io
→ composer update drupal/bluefly_theme
→ git add composer.lock
→ git commit
→ MR to release/v0.1.x
→ CI PASS → ddev drush cr → visual verify → merge

10.3 Incorrect workflow (PROHIBITED)

# WRONG: editing the installed copy
cd bluefly.io/web/themes/custom/bluefly_theme
vim src/tokens.css          ← VIOLATION: consumer projection
git add -f src/tokens.css   ← VIOLATION: force-adding producer source to consumer repo
git commit                  ← VIOLATION: wrong repository
# Producer repo is unchanged; next composer install destroys the edit

11. Cross-References

  • STD-DRUPAL-002 (Composition & Theme Governance Doctrine): Establishes DRUPAL_SITES_ARE_CONSUMERS=YES and EDIT_ACTIVE_WEB_FOLDER=NO. This standard (004) provides the detailed enforcement model.
  • STD-DRUPAL-003 (Custom Module Decomposition Contract): Governs what custom modules may contain. This standard governs where they are authored.
  • STD-WORK-001 (Durable Work Governance): Worktree isolation, one lane = one bead.
  • STD-AUTH-001 (Authority Precedence): Authority chain for standards decisions.