---
# System prepended metadata

title: 'dacquiri notes (dan, d0nut, yosh)'

---

# dacquiri notes (dan, d0nut, yosh)

github: https://github.com/resyncgg/dacquiri

- let the compiler inform what needs to be done instead of talking to people
    - this requires inverting the model from top-to-bottom
    - make the compiler enforce that the access-control has occurred for every code path
    - this lowers the boundary to author secure software
    - annotate the low level methods to do this
    
## Terminology

- **attributes**: the conditions that you'd typically write if-statements for
- **policies**: the thing we annotate methods with. They're collections of attributes. They need to be enforced ahead of time
- **entities**: the things that can have attributes on them.
- **entity store**: holds onto entities so we can use them later
    
## Dacquiri example

- say we want to enforce two properties on a function
    - user is enabled
    - user is owner of document
- we write a function assuming access is already validated
- policy enforces that the properties are checked
    - this enforces 
    
```rust
#[get("/documents/{doc_id}")]
async fn access_document(req: HttpRequest, session: Session, doc_id: Path<String>) -> impl Responder {
    let document_service = req.get_document_service();
    let doc_id = doc_id.into_inner();
    let document_meta = document_service.fetch_doc_metadata(doc_id).await?;

    // coalesce our entities
    let entities = session
        .into_entity::<"user">()
        .add_entity::<_, "document_metadata">(document_meta)?;

    // prove our properties
    let proof = entities.check_caller_owns_document::<"user", "document_metadata">()?;

    // call the protected function!
    proof.fetch_document_contents(&document_service).await
}
```

We want this trait implemented:

```rust
HasEntity<User, "user">
```

```rust
ConstraintChain<..., ..., ConstraintChain<..., .., <etc>>>
```

### How dynamic is this system?

- user is enabled
- can the user be disabled dynamically?
- answer: once you've checked, it's assumed that a property will hold
- particularly optimized for things like short-lived HTTP requests
- You can work around this tho!
    - You could have things where you re-check things by revoking permissions.
    - May introduce a "live check" attribute

Can we be specific on how this differs from with clauses

- `with`-clauses require you to defer the type ahead of time. Here the attributes are stringly typed.

## with clauses


blog post: https://tmandry.gitlab.io/blog/posts/2021-12-21-context-capabilities/

```rust
capability arena: Arena;
trait Arena {..};
struct BasicArena {..}
```

```rust
use arena::{basic_arena, BasicArena};

struct Bar<'a> {
    version: i32,
    foo: &'a Foo,
}

// Here the `with` clause is used only for invoking the `Deserialize`
// impl for Foo; we never use `basic_arena` directly.
impl<'a> Deserialize for Bar<'a>
with
    basic_arena: &'a BasicArena,
{
    fn deserialize(
        deserializer: &mut Deserializer
    ) -> Result<Self, Error> {
        let version = deserializer.get_key("version")?;
        let foo = deserializer.get_key("foo")?;
        Ok(Bar { version, foo })
    }
}
```

```rust=
fn access_document()
    with user: User
{
    ...
}
```

```rust=
fn access_document()
with
    user: User,
{
    ...
}
```

```rust=
fn access_domain()
with
    user: User,
    document: Document,
    UserOwnsDocument (with user + document),
{
    // stuff
}
```

```rust=
fn toplevel() {
}
fn access_document(doc: AccessibleDocument) {
    log(doc.user());
    
}
```

an admin may want to transfer data from one team to another
- uniqueness of type
- we don't just want to show we can transfer from a team to another team
- we want to be able to talk about _specific instances of types_

Yosh wonders whether we're missing a core type system thing:

```rust
fn square<T: Mult>(n1: T, n2: T) {..}
// no guarantee n1 and n2 are _identical_ values, only identical types
```

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=8933aa6fe11679734c8ff5aa7550f778

```rust
#![feature(generic_const_exprs)]

fn main() {
    println!("{}", multi::<10, 10>());
    //println!("{}", multi::<10, 12>());
}

fn multi<const N: u32, const M: u32>() -> u32
where
    If<{N == M}>: True
{ N * M }


struct If<const Cond: bool> {}
trait True {}
impl True for If<true> {}
```

All of dacquiri is designing around a way to narrow types. In typescript you can have a type which says: "this is an A or a B".


## Alternate

- Instead guaranteeing uniqueness of instance, factor out the authentication and make that return a new type to guarantee the validation.

```rust=
fn square(args: SquareArgs) -> i32 {
    args.x() * args.y()
}

fn make_args(x: i32, y: i32) -> SquareArgs {
    assert!(x == y);
    SquareArgs::new(x, y)
}
```

"from this point onward, guarantee that thing is validated"

```rust
let validated_user = validate_user(&user)?;
some_doc.change_author(validated_user, new_author);

// with with-clauses
with validate_user(&user)? {
    some_doc.change_author(new_author);
}
```

- Rather than validating the user and returning a validated user, instead validate the document with the user and return a new type of document.
- From a capability perspective user's are overly coarse-grained
    - You want to get rid of the user as soon as you can.
    - Instead you want to pass the document around which is a type with the permissions baked in.


```rust
let open_doc: OpenDoc = carefully_open_document(&user, doc_id)?;
open_doc.change_author(new_author);
```

https://blog.yoshuawuyts.com/state-machines-2/

```rust
let open_doc: OpenDoc<DocPermission::Admin> = ...;
let open_doc: Something<OpenDoc> = ...;
```

Thing we haven't covered with this: the intersection stuff (`OR` clauses). We should revisit this. Yosh suspects view types may help here:

```rust
let open_doc: OpenDoc<Permissions { Read: true, Write: true }> = ...;
```

Ergomics rule: if you hit 2/3 states in an enum, methods which are only available on those 2 cases should always be available if you unambiguously know that that's available.