# Access action format
This library encodes and decodes owned access mutation and discovery actions. It only defines the payload format and performs no state lookup or authorization decision.
## Public API
```rust
use kcode_k1_access_types::{
AccessId, Authorizations, GroupId, Target, TxId, UserId,
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum OwnerWitness {
User,
Group(GroupId),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum AccessAction {
Create {
target: Target,
authorizations: Authorizations,
},
Replace {
access_id: AccessId,
actor: UserId,
groups_revision: Option<TxId>,
witness: OwnerWitness,
authorizations: Authorizations,
},
EnsureDiscovery {
access_id: AccessId,
},
}
pub fn encode(
operation_id: [u8; 16],
action: &AccessAction,
) -> Result<Vec<u8>, String>;
pub fn decode(
payload: &[u8],
) -> Result<([u8; 16], AccessAction), String>;
```
The enums own all values and support owned access through ordinary pattern matching. `OwnerWitness::User` means the encoded actor is directly listed as an owner. `OwnerWitness::Group` names a listed owner group.
## Canonical version 1 wire
Every payload begins `[version=1][kind:1][operation_id:16]` and has no trailing bytes.
Create uses kind 1 followed by `[subsystem_id:20 canonical padded bytes][object_id_len:u64 LE][object_id][authorizations]`. Every object byte sequence is valid, including empty and non-UTF-8 values.
Replace uses kind 2 followed by `[access_id:12][actor_user_txid:12][groups_revision_present:1][groups_revision:12 iff present][witness_kind:1][group_id:12 iff Group][authorizations]`. Presence is 0 or 1. Witness kind 1 is direct `User`; kind 2 is `Group`.
EnsureDiscovery uses kind 3 followed by exactly `[access_id:12]`. Its complete payload is therefore `[version=1][kind=3][operation_id:16][access_id:12]` and is 30 bytes long.
Authorizations are `[owner_count:u64 LE][owner entries][viewer_count:u64 LE][viewer entries]`. An owner entry is `[kind:1][id:12]`, where kind 1 is User and 2 is Group. A viewer entry is the same for User or Group, while kind 3 is Model with a 32-byte ID.
Encoding uses the exact canonical subsystem padding and the normalized arrays exposed by `Authorizations`. Decoding reconstructs canonical identity wrappers and requires the parsed arrays to equal the output of `Authorizations::new`. It rejects empty owners, noncanonical order, duplicates, owner/viewer user or group overlap, malformed padding, invalid discriminants, unsupported versions, truncated or overflowing lengths and counts, trailing bytes, and unavailable required allocation.
## Work, allocation, and exclusions
Format parsing and byte validation are `O(payload length + subject counts)`. Authorization reconstruction additionally has the normalization complexity documented by `Authorizations::new`. Encoding computes a checked exact length and requests one exact output reservation; decoding preflights declared sizes against remaining bytes and uses fallible reservations where available. There are no arbitrary payload or subject-count caps.
All operations are synchronous and share no state. Independent calls do not coordinate. This library performs no persistence, state or Groups evaluation, randomness, transaction construction, KTO, Peering, network or other I/O. It has no retry, timeout, worker, queue, or background task.