1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! # Varlink API
//!
//! `cfsctl varlink` exposes a [varlink] RPC service over a Unix socket
//! with two interfaces:
//!
//! - **`org.composefs.Repository`** — repository lifecycle, integrity
//! checks, garbage collection, and mounting
//! - **`org.composefs.Oci`** — OCI container image operations (listing,
//! pulling, inspecting, tagging, mounting)
//!
//! This API is language-agnostic and usable from any varlink client.
//! Like the Rust crate API, it is not yet declared stable.
//!
//! [varlink]: https://varlink.org
//!
//! ## Starting the service
//!
//! ```sh
//! cfsctl varlink --address /run/composefs/composefs.sock
//! ```
//!
//! Systemd socket activation is also supported — if `cfsctl varlink` is
//! started with an activated socket, the `--address` flag is not needed.
//!
//! ## Discovering the full API
//!
//! The complete interface definitions — every method, type, and error —
//! are available at runtime via the standard varlink introspection
//! protocol. Use [`varlinkctl`] to dump them:
//!
//! ```sh
//! # List available interfaces
//! varlinkctl list-interfaces /run/composefs/composefs.sock
//!
//! # Full IDL for the Repository interface
//! varlinkctl introspect /run/composefs/composefs.sock \
//! org.composefs.Repository
//!
//! # Full IDL for the OCI interface
//! varlinkctl introspect /run/composefs/composefs.sock \
//! org.composefs.Oci
//! ```
//!
//! For `exec:`-style transports (no long-running socket), `varlinkctl`
//! can launch `cfsctl` as a subprocess:
//!
//! ```sh
//! varlinkctl introspect exec:cfsctl\ varlink org.composefs.Repository
//! ```
//!
//! [`varlinkctl`]: https://www.freedesktop.org/software/systemd/man/latest/varlinkctl.html
//!
//! ## Session model
//!
//! Repositories are accessed through opaque `u64` handles. A client
//! calls `OpenRepository` to obtain a handle, passes it to every
//! subsequent method, and releases it with `CloseRepository`. No
//! repository is opened at startup.
//!
//! ## Examples
//!
//! The examples below use `varlinkctl call`. Any varlink client works —
//! the wire format is JSON over a Unix socket.
//!
//! ### Open and close a repository
//!
//! ```sh
//! # Open the system repository (/sysroot/composefs)
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.OpenRepository '{"system": true}'
//! # → {"handle": 1}
//!
//! # Open at a specific path
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.OpenRepository \
//! '{"path": "/srv/composefs"}'
//! # → {"handle": 2}
//!
//! # Release a handle when done
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.CloseRepository '{"handle": 1}'
//! ```
//!
//! ### Check repository integrity
//!
//! ```sh
//! # Full check (verifies fs-verity on every object)
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.Fsck '{"handle": 1}'
//! # → {"ok": true, "has_metadata": true, "objects_checked": 1542, ...}
//!
//! # Fast metadata-only check (skips per-object verification)
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.Fsck \
//! '{"handle": 1, "metadata_only": true}'
//! ```
//!
//! ### List and pull OCI images
//!
//! ```sh
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Oci.ListImages '{"handle": 1}'
//! # → {"images": [{"name": "myimage:latest",
//! # "manifest_digest": "sha256:abc...", ...}, ...]}
//!
//! # Pull with streaming progress
//! varlinkctl call --more /run/composefs/composefs.sock \
//! org.composefs.Oci.Pull '{
//! "handle": 1,
//! "image": "quay.io/fedora/fedora:latest",
//! "local_fetch": "decompressed",
//! "bootable": false,
//! "more": true
//! }'
//! # Streams progress, then a final "completed" frame
//! ```
//!
//! ### Inspect, tag, and untag
//!
//! ```sh
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Oci.Inspect \
//! '{"handle": 1, "image": "myimage:latest"}'
//! # → {"manifest": "{...}", "config": "{...}", ...}
//!
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Oci.Tag '{
//! "handle": 1,
//! "manifest_digest": "sha256:abc123...",
//! "name": "myimage:v2"
//! }'
//!
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Oci.Untag \
//! '{"handle": 1, "name": "myimage:old"}'
//! ```
//!
//! ### Garbage collection
//!
//! ```sh
//! # Dry run
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.Gc \
//! '{"handle": 1, "dry_run": true, "roots": []}'
//!
//! # Collect for real
//! varlinkctl call /run/composefs/composefs.sock \
//! org.composefs.Repository.Gc \
//! '{"handle": 1, "dry_run": false, "roots": []}'
//! ```
//!
//! ### Mounting
//!
//! The `Mount` and `OciMount` methods return a detached mount file
//! descriptor via `SCM_RIGHTS`. The caller attaches it with
//! `move_mount(2)`. For overlay mounts, the caller passes upperdir and
//! workdir fds in the request.
//!
//! These methods require a varlink client that supports fd passing;
//! `varlinkctl` does not currently support this.