Extends the multitenant lfx POC with two new modes:
- --attack: same-process code in the worker reuses the run token to
read OPENAI_API_KEY directly. Confirms the design's call-out that
process-level isolation alone does not protect trusted and untrusted
components from each other inside the same worker. Uses sha256/length
instead of leaking the secret value.
- --split-workers: per-vertex capability planning from the real lfx
graph. Walks vertices, derives variables:read:* scopes from each
vertex's load_from_db fields, mints per-vertex tokens, dispatches a
worker per vertex with MT_STOP_VERTEX_ID. Untrusted vertex probes are
denied at the Runtime API; the scoped Language Model vertex runs to
completion with only its own token.
Runtime API now logs variable_denied events alongside variable_read,
giving the audit story symmetry.
Fixes a return-shape bug in worker._text_from_results that wrapped the
chat output text in a redundant dict on the happy path.
Still stubbed: does not serialize arbitrary vertex outputs between
worker processes or replace lfx's core scheduler.
Working POC of the multitenant capability boundary applied to lfx's
existing service injection. Not for merge; lives under prototypes/.
- CapabilityVariableService implements VariableServiceProtocol and is
registered via @register_service(ServiceType.VARIABLE_SERVICE),
replacing lfx's default at runtime.
- The real Basic Prompting starter project runs through lfx in a
worker subprocess whose env has been scrubbed of DB and provider
credentials.
- A short-lived run token gates variable resolution. Granted scope:
the flow completes against real OpenAI. Empty scope: the shim
returns PermissionError and lfx surfaces a ComponentBuildError.
Also establishes prototypes/ as a lint-free sandbox in the root ruff
config and pre-commit hooks (ruff, detect-secrets), matching the
existing pattern for docs/ python examples.