# [zat](https://zat.dev)
AT Protocol building blocks for zig.
this readme is an ATProto record
→ [view in zat.dev's repository](https://at-me.zzstoatzz.io/view?handle=zat.dev)
zat publishes these docs as [`site.standard.document`](https://standard.site) records, signed by its DID.
## install
```bash
zig fetch --save https://tangled.sh/zat.dev/zat/archive/main
```
then in `build.zig`:
```zig
const zat = b.dependency("zat", .{}).module("zat");
exe.root_module.addImport("zat", zat);
```
## what's here
string primitives - parsing and validation for atproto identifiers
- **Tid** - timestamp identifiers (base32-sortable)
- **Did** - decentralized identifiers
- **Handle** - domain-based handles
- **Nsid** - namespaced identifiers (lexicon types)
- **Rkey** - record keys
- **AtUri** - `at://` URIs
```zig
const zat = @import("zat");
if (zat.AtUri.parse(uri_string)) |uri| {
const authority = uri.authority();
const collection = uri.collection();
const rkey = uri.rkey();
}
```
did resolution - resolve did:plc and did:web to documents
```zig
var resolver = zat.DidResolver.init(allocator);
defer resolver.deinit();
const did = zat.Did.parse("did:plc:z72i7hdynmk6r22z27h6tvur").?;
var doc = try resolver.resolve(did);
defer doc.deinit();
const handle = doc.handle(); // "bsky.app"
const pds = doc.pdsEndpoint(); // "https://..."
const key = doc.signingKey(); // verification method
```
handle resolution - resolve handles to DIDs via HTTP well-known
```zig
var resolver = zat.HandleResolver.init(allocator);
defer resolver.deinit();
const handle = zat.Handle.parse("bsky.app").?;
const did = try resolver.resolve(handle);
defer allocator.free(did);
// did = "did:plc:z72i7hdynmk6r22z27h6tvur"
```
xrpc client - call AT Protocol endpoints
```zig
var client = zat.XrpcClient.init(allocator, "https://bsky.social");
defer client.deinit();
const nsid = zat.Nsid.parse("app.bsky.actor.getProfile").?;
var response = try client.query(nsid, params);
defer response.deinit();
if (response.ok()) {
var json = try response.json();
defer json.deinit();
// use json.value
}
```
sync types - enums for firehose/event stream consumption
```zig
// use in struct definitions for automatic json parsing:
const RepoOp = struct {
action: zat.CommitAction, // .create, .update, .delete
path: []const u8,
cid: ?[]const u8,
};
// then exhaustive switch:
switch (op.action) {
.create, .update => processUpsert(op),
.delete => processDelete(op),
}
```
- **CommitAction** - `.create`, `.update`, `.delete`
- **EventKind** - `.commit`, `.sync`, `.identity`, `.account`, `.info`
- **AccountStatus** - `.takendown`, `.suspended`, `.deleted`, `.deactivated`, `.desynchronized`, `.throttled`
json helpers - navigate nested json without verbose if-chains
```zig
// runtime paths for one-offs:
const uri = zat.json.getString(value, "embed.external.uri");
const count = zat.json.getInt(value, "meta.count");
// comptime extraction for complex structures:
const FeedPost = struct {
uri: []const u8,
cid: []const u8,
record: struct {
text: []const u8 = "",
},
};
const post = try zat.json.extractAt(FeedPost, allocator, value, .{"post"});
```
jwt verification - verify service auth tokens
```zig
var jwt = try zat.Jwt.parse(allocator, token_string);
defer jwt.deinit();
// check claims
if (jwt.isExpired()) return error.TokenExpired;
if (!std.mem.eql(u8, jwt.payload.aud, expected_audience)) return error.InvalidAudience;
// verify signature against issuer's public key (from DID document)
try jwt.verify(public_key_multibase);
```
supports ES256 (P-256) and ES256K (secp256k1) signing algorithms.
multibase decoding - decode public keys from DID documents
```zig
const key_bytes = try zat.multibase.decode(allocator, "zQ3sh...");
defer allocator.free(key_bytes);
const parsed = try zat.multicodec.parsePublicKey(key_bytes);
// parsed.key_type: .secp256k1 or .p256
// parsed.raw: 33-byte compressed public key
```
## specs
validation follows [atproto.com/specs](https://atproto.com/specs/atp).
## versioning
pre-1.0 semver:
- `0.x.0` - new features (backwards compatible)
- `0.x.y` - bug fixes
breaking changes bump the minor version and are documented in commit messages.
## license
MIT
---
[roadmap](docs/roadmap.md) · [changelog](CHANGELOG.md)