Skip to content
zit Artifact [1b3a49fddc]
Login

Artifact [1b3a49fddc]

Artifact 1b3a49fddc4e92683abf9a128f402180a07bed56a61deaf705ea82a3f46e333a:


//! Sync Protocol — draft-fossil-sync-protocol-00.
//!
//! Two repositories reconcile a content-addressed artifact set over HTTP. The
//! protocol is client-driven; the server is stateless across rounds, so only
//! the client runs a state machine (Section 3.8).

const std = @import("std");

/// The client's protocol state (Section 3.8). The server reacts to each
/// request independently and has no state machine.
pub const ClientState = enum {
    /// Operation selected; no round sent yet.
    init,
    /// First round of a modern clone: login suppressed, config/uv-hash
    /// deferred, an `error` reply ignored (Sections 8.3, 8.4, 11.1).
    clone_round0,
    /// Steady round loop: authenticated request, reply dispatched, phantom /
    /// send-queue / config / private work advances (Section 3.2).
    exchange,
    /// Clean stop: no continuation condition of Section 3.7 held.
    terminated,
    /// A fatal protocol error ended the sync without convergence.
    aborted,
};

/// The operation a sync round is performing.
pub const Operation = enum { pull, push, sync, clone };

pub const Error = error{ FatalProtocolError, NotAuthorized, NotImplemented };

/// Robustness posture (Section 3.9): conservative in what it sends, strict in
/// what it accepts. An unknown non-`pragma` operator and a malformed content
/// card are fatal; liberality is confined to the four enumerated points.
pub const Client = struct {
    state: ClientState = .init,
    operation: Operation = .sync,

    // The round loop is a sans-IO state machine: one method produces the next
    // request bytes, another consumes a reply's bytes and updates `state`; the
    // transport (real HTTP or the simulator) is owned by the caller — the server
    // is stateless, only the client keeps state (Section 3.8). The exact
    // signatures land with the sync implementation, read from the full Section 3
    // round / dispatch / termination rules. Deliberately not stubbed here so
    // nothing is built against a placeholder shape.
};

test "client starts in init" {
    const c: Client = .{};
    try std.testing.expectEqual(ClientState.init, c.state);
}