Skip to content

Bluefly Site Factory — Product Architecture

Date: 2026-06-20 Status: DRAFT — Awaiting Thomas approval before any execution Objective: Define the first Bluefly Factory Pack that generates revenue and deploys repeatedly through GitLab and IaC onto Oracle.


1. BLUEFLY PACK TAXONOMY

Six packs. Each is a Gas City pack (pack.toml + agents + formulas + hooks + config). Each can be imported independently. bluefly-core-pack is required by all others.

Pack Purpose Dependencies
bluefly-core-pack Identity (GAID), governance (Cedar), observability (tracing), blu-cli integration, receipt pipeline Gas City core
bluefly-drupal-pack Drupal Site Templates, Recipes, Drush operations, config management, DDEV/Acquia/Oracle targets bluefly-core-pack
bluefly-site-factory-pack THE REVENUE PACK. Site provisioning formulas, template catalog, customer onboarding, lifecycle management bluefly-core-pack, bluefly-drupal-pack, bluefly-infrastructure-pack
bluefly-governance-pack Cedar policy evaluation, Dragonfly verification, compliance gates, audit trail, trust posture bluefly-core-pack
bluefly-ai-pack AI module configuration, provider management, context control, knowledge broker, canvas AI bluefly-core-pack, bluefly-drupal-pack
bluefly-infrastructure-pack Oracle provisioning, NAS backup, GitLab runner management, Cloudflare tunnels, Tailscale mesh, IaC execution bluefly-core-pack

Pack Composition Rules

  • Every pack is a directory with pack.toml at root
  • Packs import via gc pack import <source>
  • Packs compose — bluefly-site-factory-pack imports bluefly-drupal-pack and bluefly-infrastructure-pack
  • No pack duplicates what Gas City already provides
  • No pack contains custom orchestration — formulas only

2. DRUPAL SITE FACTORY — THE FIRST MONETIZABLE FACTORY

What It Is

A Gas City factory that provisions production-ready Drupal sites in minutes. Customer-facing. Repeatable. Billable.

Customer Outcome

"Provision a production-ready Drupal site in minutes."

Not a demo. Not a sandbox. A production site with: - Chosen template applied - Recipes executed - Runtime provisioned (Acquia Cloud / Oracle / AWS) - CI/CD pipeline configured - Monitoring active - Backup scheduled - DNS configured - SSL provisioned

What It Is NOT

  • Not a custom installer
  • Not a Drupal multisite manager
  • Not an Acquia Site Factory clone
  • Not a hosting company

Revenue Model

Tier What They Get Price Signal
Template License Site Template + Recipes + Theme + Content Model One-time
Factory Provisioning Gas City formula execution: template → running site Per-site
Managed Lifecycle Ongoing: upgrades, backups, security patches, recipe updates Monthly
Custom Template Bluefly builds a custom template for the customer's vertical Project SOW

3. SITE FACTORY FORMULAS

These are Gas City v2 formulas. Each is an execution graph with steps, dependencies, variables, retry logic, and failure policy. Agents execute steps. The orchestrator drives completion.

Formula: create-site-from-template

The core formula. Everything starts here.

Steps:
  1. validate-template
     - Input: template_name, customer_id, target_environment
     - Action: Verify template exists in catalog, customer authorized, environment available
     - Agent: validator
     - Fail: ABORT

  2. provision-codebase
     - Input: template_name, site_name
     - Action: Clone template repo, configure composer.json, set site UUID
     - Agent: builder
     - Depends: validate-template
     - Fail: RETRY(2) then ABORT

  3. apply-recipes
     - Input: recipe_list (from template manifest)
     - Action: Execute `drush recipe:apply` for each recipe in order
     - Agent: drupal-operator
     - Depends: provision-codebase
     - Fail: RETRY(1) then ABORT

  4. configure-environment
     - Input: target_environment, site_name
     - Action: Create environment config (config_split), set env variables, configure caching
     - Agent: drupal-operator
     - Depends: apply-recipes
     - Fail: RETRY(1) then ABORT

  5. provision-runtime
     - Input: target_environment, resource_tier
     - Action: Execute IaC (Terraform/Ansible) to provision compute, database, CDN, DNS
     - Agent: infra-operator
     - Depends: configure-environment
     - Fail: ABORT (no partial infra)

  6. deploy-site
     - Input: site_name, target_environment
     - Action: GitLab CI pipeline: build → test → deploy → smoke test
     - Agent: deployer
     - Depends: provision-runtime
     - Fail: ROLLBACK(provision-runtime) then ABORT

  7. verify-site
     - Input: site_url
     - Action: HTTP health check, WCAG audit, security headers check, performance baseline
     - Agent: verifier
     - Depends: deploy-site
     - Fail: FLAG (site deployed but verification failed)

  8. emit-receipt
     - Input: all outputs from above
     - Action: Generate JSON receipt, store in NAS, notify customer
     - Agent: recorder
     - Depends: verify-site
     - Fail: LOG (never block on receipt failure)

Formula: upgrade-site

Steps:
  1. snapshot-current — Full backup (database + files + config)
  2. pull-template-updates — Fetch latest template version
  3. apply-recipe-updates — Execute new/updated recipes
  4. run-database-updates — drush updatedb
  5. deploy-updated-site — GitLab CI pipeline
  6. verify-site — Same as create flow
  7. emit-receipt
  Rollback: restore-from-snapshot at any failure after step 1

Formula: backup-site

Steps:
  1. export-database — drush sql:dump → NAS
  2. export-files — rsync public/private files → NAS
  3. export-config — drush config:export → NAS
  4. verify-backup — Integrity check on all exports
  5. emit-receipt

Formula: recover-site

Steps:
  1. select-backup — Find most recent verified backup from NAS
  2. provision-recovery-runtime — Stand up fresh environment
  3. import-database — Restore from backup
  4. import-files — Restore from backup
  5. import-config — drush config:import
  6. verify-site — Full health check
  7. dns-cutover — Point DNS to recovery environment
  8. emit-receipt

Formula: decommission-site

Steps:
  1. final-backup — Full backup to NAS with 90-day retention
  2. export-content — Content export for customer
  3. teardown-runtime — Destroy compute/database/CDN
  4. archive-codebase — Archive repo in GitLab
  5. revoke-access — Remove customer credentials/keys
  6. emit-receipt

4. BLUEFLY SITE TEMPLATES

Each template is a product. Each contains everything needed to go from zero to running site.

Template Structure

bluefly-templates/
  nonprofit/
    template.yaml          # Manifest: name, version, recipes, theme, content model
    recipes/
      nonprofit-base/      # Core Drupal recipe
      nonprofit-events/    # Events recipe
      nonprofit-donors/    # Donor management recipe
      nonprofit-blog/      # Blog recipe
    theme/
      nonprofit-theme/     # Starterkit-based theme with design tokens
    content-model/
      content_types.yaml   # Exported content type definitions
      taxonomies.yaml      # Vocabulary definitions
      media_types.yaml     # Media type definitions
    config/
      config_split/        # Environment-specific config
    tests/
      cypress/             # E2E tests for this template
    deploy/
      formula.yaml         # Gas City formula override for this template

Template Catalog

Template Target Market Recipes Included Content Types
Nonprofit 501(c)(3) orgs, foundations, charities Base, Events, Donors, Blog, Volunteer Management Event, Campaign, Donor Profile, Impact Report, Grant
Higher Education Universities, colleges, community colleges Base, Programs, Faculty, Admissions, News, Research Program, Course, Faculty Profile, Department, Research Project
Healthcare Hospitals, clinics, health systems Base, Providers, Locations, Services, Patient Resources Provider, Location, Service, Health Topic, Patient Story
SaaS Software companies, product sites Base, Pricing, Documentation, Changelog, Blog Feature, Integration, Pricing Tier, Release Note, Case Study
Membership Associations, unions, professional orgs Base, Members, Events, Resources, Directory Member Profile, Resource, Event, Chapter, Benefit
Municipality Cities, towns, counties, state agencies Base, Services, Departments, News, Public Notices, Meetings Department, Public Service, Meeting, Public Notice, Elected Official

Template Quality Bar

Every template MUST ship with: - [ ] WCAG 2.1 AA compliance (automated + manual audit) - [ ] HTTPS/security headers hardened - [ ] Performance budget: LCP < 2.5s, CLS < 0.1, FID < 100ms - [ ] Responsive: mobile, tablet, desktop - [ ] Content model documentation - [ ] Editorial workflow (draft → review → publish) - [ ] Search configured (Search API + Solr/Elasticsearch recipe) - [ ] Multilingual-ready (i18n recipe optional but composable) - [ ] Cypress E2E test suite passing - [ ] Drush commands for content seeding - [ ] GitLab CI pipeline template (.gitlab-ci.yml)


5. GAS TOWN POSITIONING

Gas City is: - A compatibility pack — operators migrating from Gas City can import gascity pack into their Gas City and retain familiar roles/commands - A migration pack — gc maps Gas City commands to Gas City primitives - A reference operating model — Mayor/Deacon/Witness/etc. are role patterns, not platform primitives

Bluefly's relationship to Gas City: - Import the gascity pack where its role patterns are useful (mayor for planning, reviewer for code review) - Extend with Bluefly-specific agents (drupal-operator, infra-operator, verifier, recorder) - Do not build around it — Bluefly agents are Gas City agents with Bluefly pack config, not Gas City roles


6. DEPLOYMENT AUTHORITY

The deployment chain is fixed. No manual paths. No SSH-and-pray.

Author (Thomas / Blu / Agent)
  → Git (GitLab, feature branch)
    → agent-buildkit (validation, linting, testing)
      → gitlab_components (reusable CI templates)
        → GitLab Ultimate (CI/CD pipeline execution)
          → IaC (Terraform/Ansible in iac/ repo)
            → Oracle (bluefly-platform.tailcf98b3.ts.net)
              → Gas City (gc supervisor on Oracle)

What Runs Where

Component Location How It Gets There
Gas City supervisor (gc) Oracle IaC: Ansible installs gc from Homebrew/tarball
Bluefly packs Oracle, in city directory GitLab CI: gc pack import from GitLab registry
Formulas Oracle, in city directory Part of pack, deployed with pack
Dolt (beads store) Oracle IaC: Ansible installs Dolt
Agent sessions (tmux) Oracle Gas City manages via tmux provider
Site codebases GitLab repos Template clone → customer repo
Site runtimes Target environment (Acquia/Oracle/AWS) Formula step: provision-runtime via IaC
Backups NAS (Synology) Formula step: backup-site via rsync/NFS
Receipts GitLab job artifacts + Beads metadata Formula step publishes evidence and records its GitLab reference in the active Bead
Cedar policies Oracle (compliance-engine) GitLab CI from cedar-policies repo
Agent Cards Oracle (ADS instance) Published by Agent Card Publisher formula

What Does NOT Run on Mac

  • Gas City supervisor
  • Agent sessions
  • Formula execution
  • Dolt database
  • Site provisioning
  • IaC execution
  • Backup operations

Mac is: blu-cli operator console, browser, editor, tmux observer.


7. BLU-CLI AS OPERATOR SURFACE

blu-cli wraps gc with Bluefly governance, identity, and operational context. Operators interact with blu, not gc directly.

Command Surface

blu pack list                    # List installed Bluefly packs
blu pack install <pack>          # Import and configure a Bluefly pack
blu pack update <pack>           # Update pack to latest version

blu formula list                 # List available formulas
blu formula run <formula> [args] # Execute a formula (triggers gc formula run)
blu formula status <id>          # Check formula execution status

blu site create <template> <name> [--env=<target>]  # Run create-site-from-template
blu site list                    # List all managed sites
blu site status <name>           # Health check on a managed site
blu site upgrade <name>          # Run upgrade-site formula
blu site backup <name>           # Run backup-site formula
blu site recover <name>          # Run recover-site formula
blu site decommission <name>     # Run decommission-site formula

blu deploy <target>              # Trigger GitLab CI deployment pipeline
blu deploy status <pipeline_id>  # Check deployment status

blu observe                      # Stream Gas City events (gc events --follow)
blu observe agents               # Agent health/status
blu observe formulas             # Running formula status
blu observe sites                # All managed sites health

blu recover <component>          # Recovery runbooks for platform components

What blu-cli Adds Over gc

Concern gc blu-cli
Identity None GAID verification, 1Password secret injection
Governance None Cedar policy pre-check before formula execution
Audit Events log Receipt generation, NAS persistence
Templates None Template catalog, version management
Observability gc events Unified view across Gas City + GitLab + Drupal
Secrets None op run integration, never plaintext

Implementation

  • blu-cli is a Node.js/TypeScript CLI (already exists in blu-cli/ repo)
  • Calls gc subprocess for Gas City operations
  • Calls GitLab API for pipeline operations
  • Calls Oracle via SSH/Tailscale for remote operations
  • All commands emit structured JSON receipts

8. FIRST FACTORY DEPLOYMENT — THE SEQUENCE

This is the execution plan to go from "we have repos" to "we have a running factory on Oracle."

Pre-requisites (already exist)

  • [x] Oracle server accessible via Tailscale
  • [x] GitLab Ultimate with gitlab_components
  • [x] agent-buildkit repo
  • [x] iac/ repo with Terraform/Ansible
  • [x] blu-cli repo (scaffolded)
  • [x] Drupal 11 expertise
  • [x] Gas City installed locally (for authoring)

Phase 1: Gas City on Oracle

  1. IaC playbook: install gc, dolt, tmux, jq, beads on Oracle
  2. gc init — create the Bluefly city
  3. Verify: gc status returns healthy city
  4. Verify: Supervisor API accessible via Tailscale (curl http://oracle:PORT/v0/cities)
  5. Receipt: {phase: 1, status: "city_running", host: "oracle", timestamp: ...}

Phase 2: Core Pack

  1. Author bluefly-core-pack/pack.toml with Bluefly agent definitions
  2. gc pack import ./bluefly-core-pack
  3. Verify: agents registered, hooks installed
  4. Test: sling a trivial bead, confirm execution + receipt
  5. Receipt: {phase: 2, status: "core_pack_installed", agents: [...], timestamp: ...}

Phase 3: First Template

  1. Build nonprofit template (recipes, theme, content model, config, tests)
  2. Test locally with DDEV: ddev start, apply recipes, verify content model
  3. Commit to GitLab, pipeline passes
  4. Receipt: {phase: 3, status: "template_verified", template: "nonprofit", timestamp: ...}

Phase 4: Site Factory Pack

  1. Author bluefly-site-factory-pack/pack.toml with formulas
  2. Implement create-site-from-template formula
  3. gc pack import ./bluefly-site-factory-pack
  4. Test: gc formula run create-site-from-template template=nonprofit name=demo-site env=dev
  5. Verify: Drupal site running at target URL
  6. Receipt: {phase: 4, status: "factory_operational", site: "demo-site", url: "...", timestamp: ...}

Phase 5: blu-cli Integration

  1. Wire blu site create → gc formula run create-site-from-template
  2. Wire blu observe → gc events --follow
  3. Test full flow: blu site create nonprofit acme-nonprofit --env=dev
  4. Verify: site created, receipt emitted, observable
  5. Receipt: {phase: 5, status: "cli_operational", command: "blu site create", timestamp: ...}

Phase 6: Customer-Ready

  1. Add remaining formulas (upgrade, backup, recover, decommission)
  2. Add governance (Cedar pre-checks on formula execution)
  3. Add monitoring (site health checks on schedule)
  4. Build second template (pick based on pipeline — likely Higher Education or Municipality)
  5. Write customer-facing docs
  6. Price it

9. WHAT THIS IS NOT

  • ❌ A Gas City tutorial
  • ❌ A custom Drupal installer
  • ❌ An Acquia Site Factory competitor (different layer)
  • ❌ A hosting company pitch
  • ❌ A framework

10. WHAT THIS IS

A product: Bluefly Site Factory Built on: Gas City (orchestration) + Drupal (platform) + GitLab Ultimate (CI/CD) + Oracle (runtime) Sold as: Templates (one-time) + Provisioning (per-site) + Lifecycle (monthly) Delivered via: Formulas (automated) through blu-cli (governed)

The factory runs without the workstation. Close the laptop, sites keep running, backups keep happening, monitoring keeps checking.


11. BLUEFLY FACTORY LIVE — the operating console

The round-trip MVP (blucity!264 + blu_fleet!17) is the integration test, not the product demo. The demo is a single visible factory run that makes the accumulated infrastructure legible as one thing.

HUMAN / DRUPAL -> GOVERNED INTENT -> GAS CITY ORDER -> FORMULA
   -> BEAD DECOMPOSITION -> PARALLEL AGENT SESSIONS
   -> WORKTREES / COMMITS / MRs / CI -> REVIEW / GOVERNANCE GATE
   -> RELEASE -> NATIVE EVENTS -> DRUPAL RECEIPT -> REPLAYABLE PROVENANCE

Gas City remains the execution authority. Drupal/ContextControl is the human operating console and governed projection — it must not reimplement orchestration, and it must not become a second work database.

The demo request is a real Drupal change, not an echo:

"Create the Governed AI Delivery service using the existing Service model and design system. Add tests and prepare it for release."

Success is that someone who knows nothing about multi-agent AI can watch the screen and understand: I asked for a business outcome, the factory planned it, split it, specialists did it, the system checked their work, a human retained authority, the change moved through delivery, and every action is replayable.

12. SUBSTRATE VERIFICATION — 2026-09-14

Section 11 depends on three Gas City surfaces. Verified against the installed runtime (gc 1.4.1) on the DRUPAL workstation seat before anything is built on them. RETRIEVED, not assumed.

Confirmed present and working

surface evidence
City + supervisor event API /v0/city/{name}/events and /v0/events, each with /stream
Live SSE gc events --follow streams continuously; JSON Lines, one API DTO or SSE envelope per line
Cursor replay --after <seq> (city scope) and --after-cursor city-a:12,city-b:9 (supervisor, multi-city)
Real event flow order.fired events observed live with sequence numbers ~1,080,000+
Event envelope {actor, payload, seq, subject, ts, type, ok} — the shape a Drupal projection consumes
Replay history .gc/events.jsonl plus rotated archives covering seq 1 → 976,434
External conversation protocol gc extmsg bind/handoff/unbind binds an external conversation to a session or a configured agent; agent bindings survive session restarts and cold-wake a session on delivery. The "front desk" handoff pattern is native. Requires the city API server — no local fallback.

Phase 2 (event model, no polling) and Phase 6 (time machine) are therefore buildable on native primitives today. Phase 5 has a real substrate in extmsg, and it is stronger than a chat bridge: conversation → agent binding is durable.

Confirmed BROKEN — fix before building the console on them

surface state
/v0/city/BluCity/agents no response, 25s timeout
/v0/city/BluCity/sessions no response, 25s timeout
/v0/city/BluCity/formulas HTTP 400 without parameters

A Factory Run page showing live agents and sessions cannot be built until the first two respond. That is a control-plane defect, not a console design problem.

The serious one — the API serves the WRONG ledger

/v0/city/BluCity/beads returns HTTP 200 and real rows, so bead reads work even while bd writes are refused. But the rows come back with the bc- prefix:

bc-wisp-7nb, bc-wisp-rwy, bc-wisp-b1s

Canonical city prefix is hq. The API is bound to the local non-canonical managed_city store, not Oracle city_canonical @ 127.0.0.1:3308/hq.

API_READ_PLANE        = HEALTHY
API_BOUND_STORE       = NON_CANONICAL (bc)
BEAD_WRITE_PLANE      = REFUSED (project-identity guard, correctly)

A console built today would faithfully render the wrong ledger. Event projection, bead links and provenance would all point at a store that is not the work authority. This is the same endpoint-binding incident as the gc mail and gc sling outage, now shown to reach the product surface.

Order of work implied

1  canonical endpoint binding        MAYOR   — gates everything below
2  agents + sessions API endpoints   FOUNDRY/MAYOR
3  gc order run --var forwarding     FOUNDRY — without it an Order cannot
                                     carry a correlation_id, so provenance
                                     cannot be threaded end to end
4  event projection + replay         DRUPAL/CONTEXTCONTROL — buildable now
5  Factory Run page                  after 1 and 2

Items 4 and the receipt/dedupe work are not blocked and are already in flight (blu_fleet!17). Items 1–3 are control-plane and owned elsewhere.