// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.pkg;

using zx;

/// This manages package repositories.
///
/// This is intended to be implemented by package resolver components, and used by
/// repository administration tools.
@discoverable
protocol RepositoryManager {
    /// Adds a repository. This will overwrite the repository if it already exists.
    ///
    /// + request `repo` a repository to add to the resolver.
    /// * error a zx_status value indicating failure. One of the following:
    ///     * `ZX_ERR_ACCESS_DENIED` if editing repositories is permanently disabled.
    ///     * `ZX_ERR_ALREADY_EXISTS` if the repository already exists.
    ///     * `ZX_ERR_INVALID_ARGS` if the repository is malformed.
    Add(struct {
        repo RepositoryConfig;
    }) -> (struct {}) error zx.status;

    /// Removes a repository.
    ///
    /// Removing a repository will prevent future packages from being cached from this repository,
    /// but in-flight downloads may not be interrupted.
    ///
    /// + request `repo_url` the URL of the repository we want to remove.
    /// * error a zx_status value indicating failure. One of the following:
    ///     * `ZX_ERR_ACCESS_DENIED` if editing repositories is permanently disabled or the
    ///       `repo_url` matches a static repository.
    ///     * `ZX_ERR_INVALID_ARGS` if the `repo_url` is malformed.
    ///     * `ZX_ERR_NOT_FOUND` if the repository does not exist.
    Remove(struct {
        repo_url string;
    }) -> (struct {}) error zx.status;

    /// Adds a mirror to a repository. This will overwrite the mirror if it already exists.
    ///
    /// + request `repo_url` the URL of the repository to add the mirror to.
    /// + request `mirror` the mirror config used to add the mirror.
    /// * error a zx_status value indicating failure. One of the following:
    ///     * `ZX_ERR_ALREADY_EXISTS` if the mirror for this repository already exists.
    ///     * `ZX_ERR_INVALID_ARGS` if the `repo_url` or the `mirror` is malformed.
    ///     * `ZX_ERR_NOT_FOUND` if the repository does not exist.
    AddMirror(struct {
        repo_url string;
        mirror MirrorConfig;
    }) -> (struct {}) error zx.status;

    /// Removes a mirror from a repository.
    ///
    /// Removing a mirror will prevent future packages from being cached from that mirror, but
    /// in-flight downloads may not be interrupted.
    ///
    /// + request `repo_url` the URL of the mirror's repository.
    /// + request `mirror_url` the URL of the mirror we want to remove.
    /// * error a zx_status value indicating failure. One of the following:
    ///     * `ZX_ERR_INVALID_ARGS` if the `repo_url` or the `mirror_url` is malformed.
    ///     * `ZX_ERR_NOT_FOUND` if the repository or mirror does not exist.
    RemoveMirror(struct {
        repo_url string;
        mirror_url string;
    }) -> (struct {}) error zx.status;

    /// Returns an iterator over all repositories.
    ///
    /// + request `iterator` a request for an iterator.
    List(resource struct {
        iterator server_end:RepositoryIterator;
    });
};

/// The configuration necessary to connect to a repository and its mirrors.
type RepositoryConfig = table {
    /// A fuchsia-pkg URL identifying the repository. Required.
    ///
    /// Example: fuchsia-pkg://example.com/
    1: repo_url string;

    /// A vector of public keys that have signed the initial trusted root
    /// metadata. Required.
    ///
    /// These keys must match one of the trusted keys known to the system.
    2: root_keys vector<RepositoryKeyConfig>;

    /// The repository mirrors that serve the package contents. Required.
    3: mirrors vector<MirrorConfig>;

    /// The package URL of the system update package. Optional.
    ///
    /// Only used for the fuchsia-pkg://fuchsia.com/ repo.
    4: update_package_url string;

    /// The initial trusted root metadata version. Optional, if absent presumed
    /// to be 1.
    ///
    /// This value describes the initial root metadata version the resolver will
    /// fetch to initialize trust, once it's signatures has been verified by the
    /// `root_keys`. It will then walk the chain of N+1, N+2, and etc to the
    /// latest version before the resolver fetches any targets.
    ///
    /// It is recommended that this `root_version` number and `root_keys ` are
    /// kept reasonably in sync with the most recent published version of the
    /// root metadata, as that avoids the risk of an old and unused root key
    /// being used to compromise resolvers during the trust initialization.
    5: root_version uint32;

    /// The number of `root_keys` that need to have signed the root metadata for it
    /// to be considered trusted. This value must be greater than or equal to 1.
    /// Optional, if absent presumed to be 1.
    6: root_threshold uint32;

    /// Whether the package resolver should check attached storage for blobs and
    /// repository metadata. Optional, if absent presumed to be false.
    7: use_local_mirror bool;

    /// Controls how repository metadata is persisted across reboots. Optional, if absent presumed
    /// to be EPHEMERAL.
    8: storage_type RepositoryStorageType;
};

/// The keys used by the repository to authenticate its packages.
///
/// The only supported algorithm at the moment is ed25519.
type RepositoryKeyConfig = flexible union {
    /// The raw ed25519 public key as binary data.
    1: ed25519_key bytes;
};

/// Where the repository storage is written to.
type RepositoryStorageType = strict enum {
    /// Ephemeral, or in-memory storage. This repository metadata will be lost
    /// when the process or device is restarted. The default type.
    EPHEMERAL = 1;

    /// Persistent, where the repository metadata is written to mutable storage
    /// and is available after a reboot.
    PERSISTENT = 2;
};

/// The configuration necessary to connect to a mirror.
type MirrorConfig = table {
    /// The base URL of the TUF metadata on this mirror. Required.
    1: mirror_url string;

    /// Whether or not to automatically monitor the mirror for updates. Required.
    2: subscribe bool;

    // TODO(fxbug.dev/75789): Turn comment below into doc-comment.
    //
    // Removed. Previously used for `RepositoryBlobKey blob_key`.
    3: reserved;

    /// The URL where blobs from this mirror should be fetched.  Optional.
    /// If absent presumed to be `mirror_url + "/blobs"`.
    4: blob_mirror_url string;
};

/// The iterator over all the repositories defined in a `PackageResolver`.
protocol RepositoryIterator {
    /// Advances the iterator and returns the next batch of repositories.
    ///
    /// - response `repos` a vector of `RepositoryConfig` repositories.
    ///   Will return an empty vector when there are no more repositories.
    Next() -> (struct {
        repos vector<RepositoryConfig>;
    });
};
