Skip to content

Workspace Spec

The workspace spec (workspace.yaml) is the kernel-level configuration file that defines the runtime environment for a LumenFlow workspace. It declares which packs are loaded, which lanes exist, what security boundaries apply, and where events and memory are stored.

# workspace.yaml
id: my-workspace
name: My Project

packs:
  - id: software-delivery
    version: '0.1.0'
    integrity: sha256:a1b2c3d4e5f6...
    source: local
    # url: optional — required for git/registry sources
    # registry_url: optional — override default registry

lanes:
  - id: framework-core
    title: 'Framework: Core'
    allowed_scopes:
      - type: path
        pattern: 'packages/@lumenflow/core/**'
        access: write
    wip_limit: 1
    # policy_overrides: optional

security:
  allowed_scopes:
    - type: path
      pattern: '**'
      access: write
    - type: network
      posture: 'off'
  network_default: 'off'
  deny_overlays:
    - '.lumenflow/**'

memory_namespace: my-workspace
event_namespace: my-workspace

All ten root keys recognized by the kernel’s WorkspaceSpecSchema:

FieldTypeRequiredManaged ByDescription
idstringYesworkspace-initUnique workspace identifier
namestringYesworkspace-initHuman-readable workspace name
packsPackPin[]Nopack:installArray of pack pins to load
lanesLaneSpec[]Nolane:editArray of lane definitions
policiesobjectNopolicy:setWorkspace-level policy overrides
securityobjectNosecurity:setWorkspace-level security config
software_deliveryobjectNoconfig:set (pack config)Software Delivery pack configuration (see below)
control_planeobjectNoconfig:set (writable root key)Control plane connection and sync settings
memory_namespacestringNoconfig:set (writable root key)Namespace for memory layer isolation
event_namespacestringNoconfig:set (writable root key)Namespace for kernel event stream isolation

Root keys fall into three categories based on how they are modified:

  1. Writable root keyscontrol_plane, memory_namespace, event_namespace. These can be written directly with config:set.
  2. Pack config keys — Keys like software_delivery that are declared by a pack’s config_key field in its manifest. Written with config:set and validated against the pack’s config schema.
  3. Managed root keysid, name, packs, lanes, policies, security. These require dedicated CLI commands (shown in the table above). Running config:set on a managed key produces an error with guidance on which command to use instead.

When a pack declares a config_key in its manifest, that key becomes a valid root-level field in workspace.yaml. For example, the Software Delivery pack declares config_key: software_delivery, which makes the software_delivery root key available.

The software_delivery field is optional. If the Software Delivery pack is not pinned in the packs array, the workspace boots without it. This allows workspaces that use other domain packs (or no packs at all) to operate with a minimal kernel-only configuration.

Each entry in the packs array is a pack pin — a versioned, integrity-checked reference to a domain pack that the kernel loads at startup.

FieldTypeRequiredDescription
idstringYesPack identifier (e.g., software-delivery)
versionstringYesSemantic version (e.g., 0.1.0)
integritystringYessha256:<64-hex> hash or dev for local development
sourcestringYesOne of local, git, or registry
urlstringNoSource URL (required for git and registry sources)
registry_urlstringNoOverride the default pack registry URL

The integrity field ensures packs cannot be tampered with. It uses the same sha256:<hex> format as Subresource Integrity (SRI):

  • sha256:<64-char-hex> — Production mode. The kernel verifies the pack manifest hash matches before loading.
  • dev — Development mode. Skips integrity verification for local pack development.
packs:
  # Production: integrity-verified
  - id: software-delivery
    version: '1.0.0'
    integrity: sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    source: registry

  # Development: skip verification
  - id: software-delivery
    version: '0.1.0'
    integrity: dev
    source: local

Each entry in lanes defines a lane at the kernel level (separate from delivery lane definitions under software_delivery.lanes.definitions).

FieldTypeRequiredDescription
idstringYesLane identifier (kebab-case, e.g., framework-core)
titlestringYesHuman-readable name (e.g., Framework: Core)
allowed_scopesToolScope[]NoScopes this lane grants (defaults to [])
wip_limitintegerNoMaximum concurrent active tasks
policy_overridesobjectNoLane-level policy configuration

The lane’s allowed_scopes are used as the second level of the scope intersection algorithm:

effective_scope = workspace ∩ lane ∩ task ∩ tool

The security object defines the workspace-level permission boundary — the outermost layer of the scope intersection.

FieldTypeRequiredDescription
allowed_scopesToolScope[]YesMaximum permissions any tool can receive
network_defaultstringYesDefault network posture: off or full
deny_overlaysstring[]YesGlob patterns for unconditionally denied paths

Scopes can be path or network types:

security:
  allowed_scopes:
    # Path scope: grant write access to all files
    - type: path
      pattern: '**'
      access: write

    # Network scope: deny all network access
    - type: network
      posture: 'off'

The network scope posture field accepts three values:

PostureDescription
offAll network access blocked
allowlistOnly traffic to listed hosts/CIDRs is permitted
fullUnrestricted network access

When posture is allowlist, the allowlist_entries field is required:

FieldTypeRequiredDescription
allowlist_entriesstring[]Yes (when posture=allowlist)Array of permitted host:port or CIDR entries
security:
  allowed_scopes:
    - type: network
      posture: allowlist
      allowlist_entries:
        - 'registry.npmjs.org:443' # host:port format
        - 'api.github.com:443' # host:port format
        - '10.0.0.0/24' # CIDR format

The kernel validates that allowlist_entries is present and non-empty when posture is allowlist. Omitting it or passing an empty array produces a Zod validation error at startup.

Network scopes participate in scope intersection across all four layers (workspace, lane, task, tool). See the scope intersection page for the deny-wins semantics and entry-level set intersection behavior.

Paths in deny_overlays are unconditionally denied regardless of scope intersection. The kernel checks these before any other authorization step:

security:
  deny_overlays:
    - '.lumenflow/**' # Kernel state is tamper-proof
    - '.git/**' # Git internals are protected

The kernel validates workspace.yaml against WorkspaceSpecSchema (defined in @lumenflow/kernel) at startup. Invalid specs cause initializeKernelRuntime() to throw with a Zod validation error.

# The kernel validates automatically during initialization.
# For manual validation, use the task:inspect command:
pnpm task:inspect --workspace-root .

The software_delivery root key is a pack config block owned by the Software Delivery pack. It exists in workspace.yaml only when the pack is pinned and declares config_key: software_delivery in its manifest.

Concernworkspace.yaml top-level (kernel)workspace.yaml > software_delivery (pack)
AudienceKernel runtimeCLI and tooling layer
LanesLaneSpec (id, scopes, wip)Lane definitions (name, code_paths)
PacksPackPin (id, version, integrity)Not present
SecurityScope intersection boundariesGit hooks, safe-git wrapper
GatesPack policies (on_completion)Gate commands (format, lint, test)
ValidationZod WorkspaceSpecSchema at initPack config schema via config:set
  • Kernel Runtime — How the workspace spec is loaded and used
  • Packs — Domain pack architecture and the Software Delivery Pack
  • Scope Intersection — How workspace security becomes effective permissions
  • Configurationsoftware_delivery configuration reference