Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/f7las-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ jobs:
'
- name: Add repo root to PYTHONPATH
run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV
- name: Install pinned OPA CLI
env:
OPA_VERSION: 1.20.2
OPA_SHA256: 69da5179ee403d10fa11bab6cfb4ffb0d23dba5f9b682fa977db772a1da5670f
run: |
mkdir -p "$RUNNER_TEMP/f7las-bin"
curl -fsSL "https://openpolicyagent.org/downloads/v${OPA_VERSION}/opa_linux_amd64_static" -o "$RUNNER_TEMP/f7las-bin/opa"
echo "${OPA_SHA256} $RUNNER_TEMP/f7las-bin/opa" | sha256sum -c -
chmod 0755 "$RUNNER_TEMP/f7las-bin/opa"
echo "$RUNNER_TEMP/f7las-bin" >> "$GITHUB_PATH"
echo "OPA_BIN=$RUNNER_TEMP/f7las-bin/opa" >> "$GITHUB_ENV"
"$RUNNER_TEMP/f7las-bin/opa" version
- name: Verify src.policy package imports
run: 'python -c "import src.policy"

Expand All @@ -48,6 +60,8 @@ jobs:
'
- name: Validate canonical data contracts
run: python scripts/validate-contracts.py
- name: Validate canonical OPA policy
run: opa check --strict config/policies/canonical-workflow.rego
- name: Run unit tests
run: 'pytest -q

Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,22 @@ Software supply-chain security is a cross-cutting supplemental domain, **Layer S
- A draft [implementation guide](docs/f7-las-implementation-guide/README.md)
- A draft [46-control catalog](docs/F7-LAS-Control-Catalog-v0.1.md)
- Architecture diagrams and engineering review material
- Canonical v1.0.0 data contracts plus illustrative prompts, policies, validators, and runtime stubs
- Canonical v1.0.0 data contracts and one synthetic, offline Python + OPA workflow
- Illustrative prompts, additional policies, validators, and runtime stubs
- Structural CI checks and prototype tests

The current code does **not** yet provide a coherent executable Layers 1–7 workflow. The existing golden-dataset runner validates scenario structure; it does not prove the described allow/deny behavior. Placeholder tests and incomplete examples are being replaced as part of the [overhaul roadmap](ROADMAP.md).
The canonical workflow provides one deliberately constrained executable Layers 1–7 path. It does not make the other examples executable or production-ready. The existing golden-dataset runner validates scenario structure; it does not prove the described allow/deny behavior. Placeholder tests and incomplete examples are being replaced as part of the [overhaul roadmap](ROADMAP.md).

## Executable versus illustrative

| Repository area | Current classification |
|---|---|
| Validation scripts | Executable structural validation |
| OPA/PDP/PEP code | Partial prototype |
| Canonical Python + OPA path | Executable for one synthetic, offline, read-only action |
| Other OPA/PDP/PEP code | Partial prototype |
| Planner, tools, sandbox, telemetry | Illustrative prototypes |
| Other policy-engine examples | Illustrative, non-canonical patterns |
| End-to-end seven-layer workflow | Planned; not yet implemented |
| Other end-to-end workflows | Planned; not yet implemented |
| Production integrations or actions | Not provided |

Nothing in this repository should be connected to production data, identities, cloud resources, security platforms, or remediation systems without independent engineering and security review.
Expand All @@ -60,6 +62,7 @@ python scripts/validate-prompts.py
python scripts/validate-policies.py
python scripts/validate-settings.py config/settings.yaml
python scripts/validate-contracts.py
opa check --strict config/policies/canonical-workflow.rego
pytest -q
```

Expand All @@ -74,6 +77,7 @@ These commands validate the **current prototype and repository structure**. They
- [Engineering review checklist](docs/Engineering-Review-Checklist.md)
- [Current QA and maturity statement](docs/F7-LAS-QA.md)
- [Canonical data contracts v1.0.0](schemas/contracts/README.md)
- [Canonical offline workflow](examples/canonical-workflow/README.md)
- [Roadmap](ROADMAP.md)
- [Security policy](SECURITY.md)

Expand Down
4 changes: 2 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Current maturity

F7-LAS is an established seven-layer reference model with a **prototype reference implementation**. The repository is not Beta and is not production-ready. Existing code and CI primarily demonstrate examples and structural validation; they do not yet prove a complete runtime control path.
F7-LAS is an established seven-layer reference model with a **prototype reference implementation**. The repository is not Beta and is not production-ready. The canonical Python + OPA workflow demonstrates one bounded, synthetic runtime control path; the broader repository remains illustrative and incomplete.

## Approved target

Expand All @@ -12,7 +12,7 @@ The target is an **Executable Reference Implementation**: one offline, determini

1. **Repository truth and terminology** — reconcile maturity, versioning, paths, licensing, unsupported claims, and private-reasoning terminology.
2. **Canonical data contracts** — define deterministic request, context, plan, proposed action, approval, decision, result, and audit records.
3. **Canonical Python + OPA path** — implement one offline, fail-closed Layers 1–7 workflow.
3. **Canonical Python + OPA path** — one offline, fail-closed Layers 1–7 workflow is implemented for the bounded synthetic action.
4. **Approval binding** — bind synthetic approval to the exact request/action digest, scope, policy version, and expiry.
5. **Behavioral scenarios** — test permitted, denied, malformed, unauthorized, unavailable, tampered, recovery, and other required paths.
6. **Evidence and replay** — correlate records, detect tampering, and reproduce deterministic outcomes.
Expand Down
38 changes: 38 additions & 0 deletions config/policies/canonical-workflow.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package f7las.canonical

default result := {
"decision": "deny",
"reason_code": "policy-denied",
"obligations": ["audit-required"],
}

expected_policy_ref := {
"policy_id": "constraints-default-v1",
"version": "v1.0",
"policy_digest": "sha256:091de3f0a96ec85a610f42456aaba98c8d04e148b9f910c570f96af37795b44d",
}

result := {
"decision": "permit",
"reason_code": "permitted-synthetic-read",
"obligations": ["audit-required", "offline-runtime-required"],
} if {
input.policy_ref == expected_policy_ref
input.approval_status == "not_required"
input.request.dry_run == false
input.request.scope.scope_id == "lab-boundary-0001"
input.request.scope.environment == "lab"
input.request.scope.resource_ids == ["workspace-0001"]
input.actor.subject_id == "investigator-0001"
input.actor.role == "investigator"
regex.match("^sha256:[0-9a-f]{64}$", input.action.action_digest)
input.action.action_digest == input.authorized_action_digest
input.action.actor_id == input.actor.subject_id
input.action.step_id == "step-0001"
input.action.tool == {"tool_id": "siem-query", "version": "1.0.0"}
input.action.operation == "workspace-health"
input.action.arguments == {"workspace_id": "workspace-0001"}
input.action.target == input.request.scope
input.action.risk_tier == "low"
input.action.requires_approval == false
}
22 changes: 18 additions & 4 deletions docs/F7-LAS-QA.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,39 @@ No. F7-LAS is an engineering and governance reference model. This repository con

## What is the current implementation maturity?

**Prototype reference implementation.** The repository does not currently contain a coherent, tested Layers 1–7 execution path. Existing validators perform useful structural checks. The existing golden-dataset evaluator validates scenario and rubric structure; it does not execute or prove the stated security behavior.
**Prototype reference implementation.** The repository contains one coherent,
tested, synthetic and offline Layers 1–7 execution path. It demonstrates a
bounded Python + OPA flow; it does not make the broader illustrative code
executable or production-ready. The existing golden-dataset evaluator validates
scenario and rubric structure; it does not execute or prove the stated security
behavior.

No current control is classified as implemented and automatically verified end-to-end. Control status will be made machine-readable and evidence-linked during the overhaul.
The canonical path has automated behavioral checks, but repository-wide control
status is not yet machine-readable or evidence-linked.

## Is the code production-ready?

No. Current planners, tools, sandboxing, telemetry, and policy adapters are incomplete or illustrative prototypes. Do not connect them to production data, accounts, identities, cloud resources, security platforms, or remediation systems.

## What is canonical?

The seven-layer model and whitepaper v3.0 are the design baseline. The future canonical executable path will be one offline, deterministic Python + OPA workflow. Other policy-engine examples are non-canonical illustrative patterns unless explicitly reclassified later.
The seven-layer model and whitepaper v3.0 are the design baseline. The canonical
executable path is the offline, deterministic Python + OPA workflow under
[`examples/canonical-workflow/`](../examples/canonical-workflow/README.md).
Other policy-engine examples remain non-canonical illustrative patterns unless
explicitly reclassified later.

## How will human approval work?

The approved design requires synthetic approval evidence bound to the exact request/action digest, arguments, target, environment, policy version, and expiry. Approval must return through PDP evaluation and PEP enforcement; it must never bypass policy or invoke a tool directly. This behavior is planned and is not yet implemented.

## How are Layer 4 and Layer 6 separated?

Layer 4 defines and validates proposed tool requests and the external action surface. A proposal is data, not authority. Layer 5 authorizes or denies it at PDP/PEP boundaries. Layer 6 constrains the environment in which an authorized simulated action runs.
Layer 4 defines and validates proposed tool requests and the external action
surface. A proposal is data, not authority. Layer 5 authorizes or denies it at
PDP/PEP boundaries. The current Layer 6 demonstration is a synthetic in-process
executor that makes no network calls; it is not an OS/container sandbox or an
enforced network-isolation boundary.

## Does F7-LAS expose internal model reasoning?

Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ This directory contains the governed documentation for the F7-LAS seven-layer re
- [Control catalog v0.1](F7-LAS-Control-Catalog-v0.1.md) — 46 draft controls across Layers 1–7.
- [Engineering review checklist](Engineering-Review-Checklist.md) — design-review aid.
- [QA and maturity](F7-LAS-QA.md) — current repository truth and limitations.
- [Canonical data contracts v1.0.0](../schemas/contracts/README.md) — machine-validated request-through-audit definitions for the future executable path.
- [Canonical data contracts v1.0.0](../schemas/contracts/README.md) — machine-validated request-through-audit definitions used by the canonical executable path.
- [Canonical offline workflow](../examples/canonical-workflow/README.md) — the bounded synthetic Python + OPA Layers 1–7 demonstration.

## Architecture graphics

Expand Down
41 changes: 41 additions & 0 deletions examples/canonical-workflow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Canonical Offline Workflow

This is the single Milestone 3 executable path across F7-LAS Layers 1–7. It is
deterministic, synthetic, offline, and fail-closed. It does not call an LLM,
cloud API, production service, or network tool.

The path uses fixed prompt intent and admission checks (Layer 1), synthetic
grounding (Layer 2), a bounded deterministic plan (Layer 3), one proposed
read-only action (Layer 4), an offline OPA CLI decision (Layer 5), a registered
synthetic in-process executor that makes no network calls (Layer 6), and
correlated canonical audit records (Layer 7). Layer 6 here is not an OS or
container sandbox and does not enforce a network-isolation boundary.

Milestone 3 uses `not_required` for the low-risk synthetic read. Binding an
explicit approval to the complete request/action/policy/scope/expiry tuple is
Milestone 4 and is intentionally not claimed here.

## Requirements

- Python 3.10 or later with `requirements.txt` installed.
- OPA CLI **1.20.2** available as `opa` or supplied with `--opa-binary`.

## Run

```bash
python -m src.canonical.cli \
--input examples/canonical-workflow/request.json \
--output /tmp/f7las-canonical-records.json \
--opa-binary opa
```

Expected summary:

```text
decision=permit execution=succeeded output=/tmp/f7las-canonical-records.json
```

If OPA is missing, times out, rejects the policy, or returns malformed output,
the workflow emits a denial and `not_executed` result. It never falls back to an
allow decision. The evidence file is preserved and the CLI returns exit status
`3` for a denied or otherwise unexecuted action.
22 changes: 22 additions & 0 deletions examples/canonical-workflow/request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"workflow_id": "workflow-0001",
"started_at": "2026-01-15T12:00:00Z",
"mission": "Evaluate synthetic lab workspace health.",
"requester": {
"subject_id": "operator-0001",
"subject_type": "human",
"role": "soc-analyst"
},
"actor": {
"subject_id": "investigator-0001",
"subject_type": "agent",
"role": "investigator"
},
"scope": {
"scope_id": "lab-boundary-0001",
"environment": "lab",
"resource_ids": [
"workspace-0001"
]
}
}
8 changes: 5 additions & 3 deletions schemas/contracts/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# F7-LAS Canonical Data Contracts

Version **1.0.0** defines eight record types for the planned deterministic,
Version **1.0.0** defines eight record types for the canonical deterministic,
offline Python + OPA reference workflow:

1. `request`
Expand Down Expand Up @@ -69,8 +69,10 @@ defaults, and self-inclusion of a digest field are not permitted.
both `record_id` and `record_digest`; action-specific records additionally bind
the exact `action_digest`.

Milestone 2 defines and validates these contracts. It does not claim that OPA
evaluation, approval enforcement, sandbox containment, or replay is operational.
Milestone 2 defined these contracts, and the Milestone 3 canonical workflow now
emits and validates them around a real offline OPA decision. This does not claim
that explicit approval binding, OS/container sandbox containment, enforced
network isolation, or replay is operational.

## Validate

Expand Down
49 changes: 11 additions & 38 deletions scripts/validate-contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from __future__ import annotations

import hashlib
import json
import sys
from collections import Counter
Expand All @@ -14,26 +13,22 @@
import rfc8785
from jsonschema import Draft202012Validator, FormatChecker


REPO_ROOT = Path(__file__).resolve().parents[1]
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))

from src.canonical.contracts import (
calculate_action_digest,
calculate_output_digest,
calculate_record_digest,
digest_payload,
)


SCHEMA_PATH = REPO_ROOT / "schemas" / "contracts" / "f7las-records-v1.schema.json"
EXAMPLES_DIR = REPO_ROOT / "schemas" / "contracts" / "examples"
POLICY_DIR = REPO_ROOT / "config" / "policies"

ACTION_DIGEST_FIELDS = (
"request_ref",
"context_ref",
"plan_ref",
"step_id",
"actor_id",
"tool",
"operation",
"arguments",
"target",
"risk_tier",
"requires_approval",
)

FORBIDDEN_KEYS = {
"api_key",
"chain_of_thought",
Expand All @@ -59,28 +54,6 @@ def load_json(path: Path) -> Any:
return json.load(handle, object_pairs_hook=reject_duplicate_keys)


def digest_payload(domain: str, value: Any) -> str:
canonical = rfc8785.dumps(value)
material = f"F7-LAS:{domain}:1.0.0\n".encode("utf-8") + canonical
return f"sha256:{hashlib.sha256(material).hexdigest()}"


def calculate_record_digest(record: dict[str, Any]) -> str:
payload = {key: value for key, value in record.items() if key != "record_digest"}
return digest_payload(f"record:{record['record_type']}", payload)


def calculate_action_digest(action: dict[str, Any]) -> str:
return digest_payload(
"action",
{field: action[field] for field in ACTION_DIGEST_FIELDS},
)


def calculate_output_digest(output: dict[str, Any]) -> str:
return digest_payload("output", output)


def load_policy_registry() -> dict[str, dict[str, Any]]:
registry: dict[str, dict[str, Any]] = {}
for path in sorted(POLICY_DIR.glob("*.json")):
Expand Down
5 changes: 5 additions & 0 deletions src/canonical/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Canonical deterministic F7-LAS reference workflow."""

from .workflow import CanonicalWorkflow, WorkflowError

__all__ = ["CanonicalWorkflow", "WorkflowError"]
37 changes: 37 additions & 0 deletions src/canonical/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Command-line entry point for the canonical offline workflow."""

from __future__ import annotations

import argparse
import json
from pathlib import Path

from .workflow import CanonicalWorkflow, WorkflowError


def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--input", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
parser.add_argument("--opa-binary", default="opa")
args = parser.parse_args()

try:
with args.input.open("r", encoding="utf-8") as handle:
workflow_input = json.load(handle)
result = CanonicalWorkflow(opa_binary=args.opa_binary).run(workflow_input)
except (OSError, json.JSONDecodeError, WorkflowError) as exc:
print(f"F7-LAS canonical workflow refused input: {exc}")
return 2

args.output.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
decision = next(record for record in result["records"] if record["record_type"] == "policy_decision")
execution = next(record for record in result["records"] if record["record_type"] == "execution_result")
print(f"decision={decision['decision']} execution={execution['status']} output={args.output}")
if decision["decision"] != "permit" or execution["status"] != "succeeded":
return 3
return 0


if __name__ == "__main__":
raise SystemExit(main())
Loading
Loading