///|
fn main {
  let engine = @policy.PolicyEngine::new()
  let engineering = @policy.ObjectRef::new("folder", "engineering")
  let roadmap = @policy.ObjectRef::new("document", "roadmap")
  let developers = @policy.ObjectRef::new("group", "developers")
  let alice = @policy.SubjectRef::direct("user", "alice")
  let bob = @policy.SubjectRef::direct("user", "bob")

  ignore(
    engine.add_tuple(@policy.RelationTuple::new(developers, "member", alice)),
  )
  ignore(
    engine.add_tuple(
      @policy.RelationTuple::new(
        engineering,
        "viewer",
        @policy.SubjectRef::userset("group", "developers", "member"),
      ),
    ),
  )
  ignore(
    engine.add_tuple(
      @policy.RelationTuple::new(
        roadmap,
        "parent",
        @policy.SubjectRef::direct("folder", "engineering"),
      ),
    ),
  )
  ignore(engine.add_tuple(@policy.RelationTuple::new(roadmap, "blocked", bob)))

  ignore(
    engine.add_rule(
      @policy.PolicyRule::direct_allow("folder", "view", "viewer"),
    ),
  )
  ignore(
    engine.add_rule(
      @policy.PolicyRule::traverse_allow("document", "view", "parent", "view"),
    ),
  )
  ignore(
    engine.add_rule(
      @policy.PolicyRule::direct_deny("document", "view", "blocked"),
    ),
  )

  println(engine.stats().to_json())
  println(engine.check(roadmap, "view", alice).to_json())
  println(engine.check(roadmap, "view", bob).to_json())
  println(engine.to_json())
}