This directory contains the formal specifications and proofs for the Provability Fabric permission system.
The Policy.lean file in this directory is the canonical Policy module (root Lake package no longer mirrors it). It implements a unified permissions system that combines:
- Unified Action Space: Single
Actiontype covering tools, documents, and grants - Executable Decider:
permitDfunction that returnsBoolfor runtime decisions - Formal Specification:
Permitproposition for mathematical reasoning - IFC-aware Access: Field-level read/write with label flow control
- Non-interference: Monitor state and global NI properties
Principal: User/service with roles, org, and attributesCtx: Runtime context including session, epoch, tenant, and attributesDocId: Document identifier with URI and version
Action.Call tool: Tool invocation (SendEmail, LogSpend, etc.)Action.Read doc path: Field-level document readAction.Write doc path: Field-level document writeAction.Grant principal action: Permission delegation
Label: Security classification (Public, Internal, Confidential, Secret)Label.le: Label ordering for information flow controlflowsOrDeclassified: Check if label flows or is declassifiedCanReadField/CanWriteField: Field-level access with label checks
World α: Abstract interface for document metadata and labelsgetLabel: Get document security labelgetMeta: Get document metadata (owner, ACL, etc.)getFieldLabel: Get field-specific security label
theorem soundness : ∀ (u : Principal) (a : Action) (γ : Ctx),
permitD u a γ = true → Permit u a γProof: If the executable decider returns true, then the formal specification holds.
theorem completeness : ∀ (u : Principal) (a : Action) (γ : Ctx),
Permit u a γ → permitD u a γ = trueProof: If the formal specification holds, then the executable decider returns true.
theorem read_requires_label_flow : ∀ (u : Principal) (doc : DocId) (path : List String) (γ : Ctx),
¬u.roles.contains "admin" ∧
(∀ (α : Type) (world : World α) (w : α),
match world.getLabel w doc with
| some doc_label =>
let user_label := Label.Internal
¬flowsOrDeclassified user_label doc_label γ.attributes
| none => False) →
permitD u (Action.Read doc path) γ = falseProof: If label doesn't flow and no declass rule matches, read is denied.
theorem ni_bridge : ∀ (u : Principal) (a : Action) (γ : Ctx) (monitor : NIMonitor) (prefixes : List NIPrefix),
permitD u a γ = true →
(∀ prefix ∈ prefixes, monitor.accepts_prefix prefix) →
GlobalNonInterference monitor prefixesProof: If permitD accepts and \MonNI accepts all prefixes, global non-interference holds.
NIMonitor: Tracks prefixes, active sessions, violations, and audit timestampsNIEvent: Individual events with input/output labels and data pathsNIPrefix: Event sequences with input/output label constraints
def NIMonitor.accepts_prefix (monitor : NIMonitor) (prefix : NIPrefix) : Prop :=
monitor.active_sessions.length > 0 ∧
¬prefix.violates_ni ∧
monitor.violation_count < 1000def GlobalNonInterference (monitor : NIMonitor) (prefixes : List NIPrefix) : Prop :=
∀ prefix ∈ prefixes, monitor.accepts_prefix prefix ∧
∀ prefix1 prefix2 ∈ prefixes,
prefix1.input_label = prefix2.input_label →
prefix1.output_label = prefix2.output_labeldef testPrincipal : Principal :=
{ id := "test-user", roles := ["email_user", "reader"], org := "test-org", attributes := [] }
def testCtx : Ctx :=
{ session := "session-1", epoch := 1, attributes := [], tenant := "test-tenant", timestamp := 1234567890 }
-- User can send emails
example : permitD testPrincipal (Action.Call Tool.SendEmail) testCtx = true := by
simp [permitD, testPrincipal, testCtx]
-- User cannot make network calls
example : permitD testPrincipal (Action.Call Tool.NetworkCall) testCtx = false := by
simp [permitD, testPrincipal, testCtx]def testMonitor : NIMonitor :=
{ prefixes := [], active_sessions := ["session1"], violation_count := 0, last_audit := 1234567890 }
def testPrefix : NIPrefix :=
{ prefix_id := "test-prefix", events := [], input_label := Label.Internal,
output_label := Label.Public, created_at := 1234567890, last_updated := 1234567890 }
-- Monitor accepts valid prefix
example : testMonitor.accepts_prefix testPrefix = true := by
simp [NIMonitor.accepts_prefix, testMonitor, testPrefix]
simp [NIPrefix.violates_ni]To build the proofs:
cd proofs
lake buildOr from the root directory:
lake buildThe system maintains a clear separation between:
- Specification (
Permit): Mathematical proposition for reasoning - Decider (
permitD): Executable function for runtime decisions
This split enables:
- Formal verification of security properties
- Efficient runtime enforcement
- Clear audit trail of decisions
Document access is controlled at the field level using:
- Path-based field identification (
List String) - Label flow checking with
flowsOrDeclassified - Integration with Merkle tree witnesses (planned)
The context includes an epoch field for:
- Permission snapshot management
- Safe revocation procedures
- Finite monitor state domains
- Complete Proofs: Finish the
sorryplaceholders with detailed proofs - Witness Integration: Add Merkle path validation to field access
- Declass Rules: Implement declassification rule evaluation
- Performance: Optimize the executable decider for high-throughput scenarios
- Integration: Connect with ActionDSL and runtime enforcement