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.tomlat root - Packs import via
gc pack import <source> - Packs compose —
bluefly-site-factory-packimportsbluefly-drupal-packandbluefly-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-cliis a Node.js/TypeScript CLI (already exists inblu-cli/repo)- Calls
gcsubprocess 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-buildkitrepo - [x]
iac/repo with Terraform/Ansible - [x]
blu-clirepo (scaffolded) - [x] Drupal 11 expertise
- [x] Gas City installed locally (for authoring)
Phase 1: Gas City on Oracle¶
- IaC playbook: install
gc,dolt,tmux,jq,beadson Oracle gc init— create the Bluefly city- Verify:
gc statusreturns healthy city - Verify: Supervisor API accessible via Tailscale (
curl http://oracle:PORT/v0/cities) - Receipt:
{phase: 1, status: "city_running", host: "oracle", timestamp: ...}
Phase 2: Core Pack¶
- Author
bluefly-core-pack/pack.tomlwith Bluefly agent definitions gc pack import ./bluefly-core-pack- Verify: agents registered, hooks installed
- Test: sling a trivial bead, confirm execution + receipt
- Receipt:
{phase: 2, status: "core_pack_installed", agents: [...], timestamp: ...}
Phase 3: First Template¶
- Build
nonprofittemplate (recipes, theme, content model, config, tests) - Test locally with DDEV:
ddev start, apply recipes, verify content model - Commit to GitLab, pipeline passes
- Receipt:
{phase: 3, status: "template_verified", template: "nonprofit", timestamp: ...}
Phase 4: Site Factory Pack¶
- Author
bluefly-site-factory-pack/pack.tomlwith formulas - Implement
create-site-from-templateformula gc pack import ./bluefly-site-factory-pack- Test:
gc formula run create-site-from-template template=nonprofit name=demo-site env=dev - Verify: Drupal site running at target URL
- Receipt:
{phase: 4, status: "factory_operational", site: "demo-site", url: "...", timestamp: ...}
Phase 5: blu-cli Integration¶
- Wire
blu site create→gc formula run create-site-from-template - Wire
blu observe→gc events --follow - Test full flow:
blu site create nonprofit acme-nonprofit --env=dev - Verify: site created, receipt emitted, observable
- Receipt:
{phase: 5, status: "cli_operational", command: "blu site create", timestamp: ...}
Phase 6: Customer-Ready¶
- Add remaining formulas (upgrade, backup, recover, decommission)
- Add governance (Cedar pre-checks on formula execution)
- Add monitoring (site health checks on schedule)
- Build second template (pick based on pipeline — likely Higher Education or Municipality)
- Write customer-facing docs
- 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.