Scope Intersection
Scope intersection is the permission model at the heart of LumenFlow’s security. Before any tool executes, the kernel computes the intersection of four independent scope layers. A tool can only operate within the permissions that all four layers jointly permit.
The Four Layers
Section titled “The Four Layers”| Layer | Source | Who controls it | Example |
|---|---|---|---|
| Workspace | workspace.yaml security.allowed_scopes | Workspace administrator | src/** (read+write), no network |
| Lane | Lane configuration allowed_scopes | Lane owner | src/core/** (write), ** (read) |
| Task | Task spec declared_scopes | Task author | src/core/auth/** (write) |
| Tool | Pack manifest required_scopes | Pack author | ** (write) — tool needs write access |
The intersection narrows progressively:
The tool can only write to src/core/auth/**. Even though the tool itself requests ** (everything), the workspace, lane, and task scopes constrain it.
How Intersection Works
Section titled “How Intersection Works”For each scope type (path-read, path-write, network), the kernel:
- Takes every possible combination across the four layers
- Checks that all four patterns overlap (using
micromatchas the matching library) - Selects the narrowest pattern by specificity score (literal characters minus wildcard penalties)
- Deduplicates results by
access:patternkey
If any layer provides zero scopes for a given access type, the result for that access type is empty — which means denial.
Empty intersection = denial
Section titled “Empty intersection = denial”The workspace and lane have no overlapping write patterns, so the intersection is empty and the tool call is denied.
Scope Types
Section titled “Scope Types”LumenFlow supports two scope types:
Path scopes
Section titled “Path scopes”Path patterns use glob syntax (* for single segment, ** for any depth). The kernel uses micromatch for pattern matching and a synthetic-path heuristic for containment checking.
Network scopes
Section titled “Network scopes”Network scopes control whether a tool can access the network and, if so, which hosts it can reach. The posture field accepts three values:
| Posture | Behavior |
|---|---|
off | All network access blocked |
allowlist | Only traffic to explicitly listed hosts/CIDRs is permitted |
full | Unrestricted network access |
Network allowlist
Section titled “Network allowlist”When posture is allowlist, the scope must include an allowlist_entries array listing permitted destinations:
Each entry is either a host:port pair (e.g., registry.npmjs.org:443) or a CIDR block (e.g., 10.0.0.0/24). The allowlist_entries field is required when posture is allowlist and must contain at least one entry.
Network intersection semantics
Section titled “Network intersection semantics”Network posture intersection follows deny-wins semantics across the four scope layers:
offblocks everything. If any layer declaresoff, the tool cannot use the network regardless of what other layers say.fullis compatible withallowlist. When one layer declaresfulland another declaresallowlist, the effective posture downgrades toallowlist. Thefulllayer imposes no restriction, so theallowlistlayer’s entries apply.- Allowlist entries are set-intersected. When multiple layers declare
allowlist, only entries present in all layers survive the intersection. An entry must appear in every restricting layer to be permitted.
If the intersection produces an empty entry set, the result is denial — the tool cannot access the network.
Reserved Path Protection
Section titled “Reserved Path Protection”Regardless of what scopes are configured, the kernel unconditionally denies writes to .lumenflow/**. This protects the kernel’s own state (event log, evidence store, task specs) from being modified by any tool, even if all four scope layers would otherwise allow it.
This check runs before scope intersection — it cannot be overridden by any configuration.
Security Properties
Section titled “Security Properties”The 4-level model provides several guarantees:
- Principle of least privilege. Each layer narrows permissions. A broad tool scope is constrained by a narrow task scope.
- No privilege escalation. A lower layer cannot grant permissions that a higher layer denied. The intersection can only shrink, never grow.
- Fail-closed. Empty intersection = denied. Missing scopes at any layer = denied. The safe direction is always denial.
- Defense in depth. Even if one layer is misconfigured (e.g.,
**for everything), the other three layers still constrain the effective scope.
Example: Multi-Lane Workspace
Section titled “Example: Multi-Lane Workspace”Consider a workspace with two lanes and a tool that writes files:
An agent working in the “Framework Core” lane on a task scoped to src/core/auth/** can write to src/core/auth/** — but cannot touch src/components/ (lane boundary) or docs/ (task boundary), even though the workspace allows **.
Next Steps
Section titled “Next Steps”- Kernel Runtime — Where scope intersection happens in the execution pipeline
- Policy Engine — The policy layer that runs alongside scope checks
- Packs — How tools declare their required scopes
- Lanes — How lanes define scope boundaries