# `type.key_as_value`

A key held as data is read as a value, when it goes only into a key-type field or a `crypto` call's `key:`.

Area 19, [Standard library](../topics/standard-library.md); not declinable; the next step is usually the agent's.

## Why Jadpo refuses it

A key made by `crypto.new_key`, or read from a key-type field, is opaque.
Returned, logged, compared or turned into text, it would leave the one place
that keeps it safe, and a key that has been read has to be treated as lost.

## What it looks like

A function that hands a device's key to its caller:

```jadpo
config {
    field_encryption_key: EncryptionKey
}

application {
    field_encryption_key: config.field_encryption_key
}

/// A tablet, with a key of its own.
entity Tablet {
    id: Uuid
    device_key: EncryptionKey
}

/// The device's key.
function key_of(tablet: Tablet) -> EncryptionKey {
    return tablet.device_key
}
```

```text
error: `tablet.device_key` is a key, read as a value
 --> main.jadpo:17:12
   |
17 |     return tablet.device_key
   |            ^^^^^^^^^^^^^^^^^ a key, read here
  reason: A key held as data is opaque: code never reads, prints, compares, returns or passes on a key, so it goes only into a key-type field, which keeps it sealed, or a `crypto` call's `key:`.
  next: Give `tablet.device_key` only as a `crypto` call's `key:`, or set a key-type field to it (agent)
  rule: type.key_as_value
  help: https://jadpo.dev/docs/errors/type.key_as_value

check failed: 1 error, 1 file
```

`(agent)` at the end of the `next:` line means your coding agent can make the
fix itself: the key goes to the operation, so the operation moves to where the
key is.

## How to fix it

**If something needs the key**, do it where the record is, giving the key as
the call's `key:`:

```jadpo
    return Sealed(crypto.encrypt(note, key: tablet.device_key, context: "note"))
```


The key never leaves the runtime, and what it sealed may go anywhere.

**If you only need to know whether a device has a key**, make the field
optional and compare it with `none`:

```jadpo
    return Keyed(tablet.device_key != none)
```


That says nothing of the key itself, and a `match` on it binds the key under
another name, for a `crypto` call's `key:`.

## Related

- [A key is never a value](../topics/hashing-and-cryptography.md#a-key-is-never-a-value)
- [`configuration.secret_flow`](configuration.secret_flow.md)
