// 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(RepositoryConfig repo) -> () 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(string repo_url) -> () 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(string repo_url, MirrorConfig mirror) -> () 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(string repo_url, string mirror_url) -> () error zx.status;

    /// Returns an iterator over all repositories.
    ///
    /// + request `iterator` a request for an iterator.
    List(request<RepositoryIterator> iterator);
};

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

    /// 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: vector<RepositoryKeyConfig> root_keys;

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

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

    /// 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: uint32 root_version;

    /// 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: uint32 root_threshold;

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

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

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

/// Where the repository storage is written to.
enum RepositoryStorageType {
    /// 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.
table MirrorConfig {
    /// The base URL of the TUF metadata on this mirror. Required.
    1: string mirror_url;

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

    // 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: string blob_mirror_url;
};

/// 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() -> (vector<RepositoryConfig> repos);
};
