Skip to content

STD-ARCH-001: Bluefly Factory Interface Contract

Status: Architecture Standard — Candidate Authority: Thomas (Bluefly Principal) Target Standard: STD-FACTORY-INTERFACE-001 Date: 2026-09-24 Supersedes: All prior agent-authored architecture assumptions about Gas City ↔ Drupal integration


One Sentence

ContextControl is the governed human interface and read model; Gas City is the sole execution orchestrator; Beads carry durable work; Formulas materialize repeatable operations; Events synchronize state; Drupal ECA and API Normalization compose the interface without custom glue; Tailscale/private hardened-city access connects trusted Bluefly systems, while narrowly governed webhooks handle external systems.


Communication Architecture

HUMAN / SYSTEM
      │
      ▼
CONTEXTCONTROL
  identity + scope + intent + policy + approval
      │
      │  governed request
      ▼
  GAS CITY API
      │
      ▼
  BEAD / FORMULA / AGENT
      │
      ├───────────► Agent A
      │                │
      │                ▼
      │             result
      │                │
      │            Bead update
      │                │
      ├───────────► Agent B
      ▼
  EVENT STREAM
      │
      ▼
  CONTEXTCONTROL READ MODEL
      │
      ▼
  CUSTOMER UI / AG-UI / EVIDENCE

Four Communication Planes

Plane Authority Purpose
Work Beads What work exists, ownership, dependencies, readiness, status
Execution Agents + Formulas + Sessions Actually perform bounded work
Observation Events What happened, transitions, request completion, runtime facts
Human/Control ContextControl Who can request, approve, inspect, govern, and understand work

Laws

BEADS != EVENTS
EVENTS != COMMANDS
MAIL != WORK AUTHORITY
CONTEXTCONTROL != ORCHESTRATOR

Five Interface Stages

Every integration maps to:

Stage Description
1. REQUEST Human/system asks for an operation
2. AUTHORIZE Identity, scope, and policy are established
3. EXECUTE Gas City materializes Beads/Formulas/Agents
4. OBSERVE Events provide typed, cursor-based state transitions
5. PROVE ContextControl presents evidence and receipts

Drupal Mapping

Stage Implementation
REQUEST ContextControl Operation entity
AUTHORIZE Drupal access + Group + Cedar
EXECUTE Gas City Formula
OBSERVE Gas City Event stream
PROVE ContextControl Evidence entities

GitLab Mapping

Stage Implementation
REQUEST Webhook / MR event
AUTHORIZE Webhook verification + service identity
EXECUTE Gas City
OBSERVE GitLab pipeline event + Gas City event
PROVE MR + CI + runtime evidence

Agent-to-Agent Mapping

Stage Implementation
REQUEST Bead
AUTHORIZE Routing + agent scope
EXECUTE Sling / session
OBSERVE Events
PROVE Bead/evidence receipt

Agent-to-Agent Communication

AGENT A
    │
    │  updates work
    ▼
  BEAD
    │
    │  ownership transition
    ▼
  SLING / ROUTE
    │
    ▼
  AGENT B

MAIL = notification/context only
EVENT = observation/proof only

Law

MAIL_SENT != WORK_ACCEPTED

If Agent A needs Agent B to perform work:

  1. Bead exists
  2. Prerequisites recorded
  3. Dependencies recorded
  4. Evidence attached
  5. Ownership/routing changed
  6. Agent B receives work

Do NOT send a giant prompt. Route durable work.


Formula V2 as Workflow Compiler

A repeatable operation becomes:

FORMULA
    │
    ├── DETECT bead
    ├── UNDERSTAND bead
    ├── MATCH bead
    ├── AUTHORIZE bead
    ├── ACT bead
    ├── VERIFY bead
    └── PROVE bead

Gas City Formula V2 materializes each step as an independent Bead and routes the graph when the formula is slung.

ContextControl visualizes:

Operation
  ├─ Detection    COMPLETE
  ├─ Understanding COMPLETE
  ├─ Match        COMPLETE
  ├─ Authorization WAITING
  ├─ Action       BLOCKED
  ├─ Verification NOT STARTED
  └─ Evidence     NOT STARTED

No new workflow engine.


ContextControl = Factory Read Model

Gas City = operational truth
ContextControl = governed human projection

ContextControl materializes only what humans need:

  • Organization
  • Team
  • Estate / Project
  • Operation
  • Agent
  • Capability
  • Approval
  • Evidence
  • Decision
  • Policy
  • Cost
  • Receipt

Group model provides:

Organization
  ├── Teams
  └── Projects / Estates
        └── Operations
              ├── Evidence
              ├── Decisions
              └── Approvals

Do NOT copy the Beads database into Drupal as another work authority.


API Normalization as Adapter

Gas City OpenAPI
      │
      ▼
  api_normalization
      │
      ├── API definitions
      ├── endpoint entities
      ├── Tool API projections
      └── ECA actions/events
      │
      ▼
  ContextControl

Curated Capability Surface

Read-only capabilities (start here):

  • City status
  • Ready work (beads/ready)
  • Operation graph
  • Agent state
  • Run state
  • Evidence
  • Usage / cost
  • Event stream

Governed commands (add after read-only works):

  • Request operation
  • Approve operation
  • Reject operation
  • Cancel operation
  • Resume operation

Never expose:

  • Arbitrary bead mutation
  • Arbitrary session creation
  • Arbitrary config mutation
  • Arbitrary shell execution

Events Populate the UI

Prefer event-driven over polling.

Gas City supports typed, cursor-based event streams with SSE and asynchronous completion via request_id.

Gas City Event
      │
      ▼
  event subscriber
      │
      ▼
  ECA
      │
      ▼
  Drupal read model update

Event → Action Mapping

Event Action
bead.created Create/update Operation state
bead.closed Advance Operation
session.started Agent becomes active
session.stopped Update agent state
request.failed Create intervention
run.step.completed Update workflow timeline
usage fact Update economic receipt

Polling = recovery/reconciliation mechanism, not primary architecture.


Drupal Commands via ECA

Human clicks APPROVE
      │
      ▼
  Drupal permission check
      │
      ▼
  Group/project scope check
      │
      ▼
  Cedar / ContractPlane policy
      │
      ▼
  ECA
      │
      ▼
  api_normalization Tool
      │
      ▼
  Gas City API
      │
      ▼
  202 ACCEPTED
      │
      ▼
  request_id
      │
      ▼
  Event stream
      │
      ▼
  Operation updated

Browser does not wait for an Agent. Drupal does not poll. Gas City executes asynchronously.


Network Architecture

Law: Gas City stays loopback-bound

Gas City 127.0.0.1:8372
      │
      ▼
  PRIVATE AUTHENTICATED EDGE
      │
      ▼
  Tailscale

Do NOT bind 0.0.0.0:8372 and say "Tailscale protects it."

Service identity: factory-api.blutown.ai or Tailscale service identity. Host identity and service identity remain separate.

Two Trust Paths

Internal (Bluefly-controlled agents + ContextControl):

ContextControl → Tailscale/private edge → Gas City API

External (GitLab SaaS, third parties):

GitLab
  │
  ▼
hooks.blutown.ai
  │
  ▼
Cloudflare edge
  │
  ▼
Gas City declared webhook
  │
  ▼
Event / Order / Bead

Surfaces

Surface Access Purpose
factory.blutown.ai Tailscale-only, authenticated Private Factory API
hooks.blutown.ai Narrowly exposed, verified, rate-limited External inbound webhooks

Do NOT expose the whole supervisor via events.blutown.ai.


Trust Boundaries

ContextControl exposes per-capability:

CAPABILITY          Drupal Security Update
TRUST CLASS         Privileged execution
INPUTS              Untrusted
ALLOWED EXECUTOR    Drupal Update Agent
AUTHORIZATION       Customer security-update policy
APPROVAL            Automatic < minor update
                    Human approval > major update
EXECUTION INTERFACE Composer / Drush
VERIFICATION        Drupal bootstrap + tests + rendered check
EVIDENCE            MR + CI + runtime receipt

Gas City Trust Law

  • city.toml, Packs, provider scripts, startup commands = trusted operator code
  • Bead text, formula variables, PR text, API fields = untrusted data
  • Never concatenate untrusted data into shell commands

Identity Model

ContextControl stores:

  • Canonical raw identity
  • Display identity
  • OSSA manifest ID
  • Gas City qualified identity (rig/agent vs city/agent — never collapse)
  • Service identity
  • Human owner

Never infer identity from a pretty session name.


Beads Topology

RAW BD = scope-local authority
GC = Factory-wide operational view

Multiple scopes share one Dolt server with different issue prefixes. bd list shows scope-local. gc ready federates across stores.

Do not assume bd list = entire Factory.


Agent Sessions Are Replaceable

ContextControl sees:

Agent → Session

Not:

tmux pane

The session provider interface (tmux, herdr, containers, ACP) is an implementation detail.


Beads Providers Are Replaceable

Integrate with:

Gas City Bead semantics (create/get/update/close/reopen/list/ready/metadata/dependencies)

Not:

Dolt SQL schema

No Drupal SQL reader against Dolt. No custom replica. No custom work tracker.


Remote Hardened City

MAC / DEVELOPER
      │
      │  gc --context production
      ▼
PRIVATE HARDENED ORACLE CITY
      │
      ├─ API
      ├─ Beads
      ├─ Events
      └─ Sessions

Stop trying to make Mac bd equal Oracle bd. Determine whether the supported remote-City model already removes the need.


Managed City Endpoints

Stop inventing:

  • ~/.beads/config.yaml hacks
  • BEADS_DOLT_SERVER_PORT hacks
  • Manual mirror files

Adopt:

gc rig set-endpoint
gc doctor managed_city origin

First Vertical Slice

Build ONE real, safe, visible operation:

CONTEXTCONTROL "Run Drupal Estate Audit"
      │
      ▼
  Policy check
      │
      ▼
  POST governed request
      │
      ▼
  GAS CITY
      │
      ▼
  DrupalWorks audit Formula
      │
      ▼
  Beads materialized
      │
      ▼
  Drupal Agent runs audit
      │
      ▼
  events stream
      │
      ▼
  ContextControl operation timeline
      │
      ▼
  Evidence displayed

No mutation. No deployment. No security update. Just a real, safe, visible operation.

Then graduate:

  1. Run security readiness audit
  2. Run release readiness audit
  3. Run config drift audit
  4. Run accessibility audit
  5. Run contrib audit

Same Factory Interface Contract. Then graduate to writes.