// 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;

/// Manages package repositories.
///
/// This interface is intended to be implemented by package resolver components, and used by
/// repository administration tools.
[Discoverable]
protocol RepositoryManager {
    /// Add a repository. This will overwrite the repository if it already exists.
    ///
    /// Arguments:
    /// * `repo` is repository to add to the resolver.
    ///
    /// Return Values:
    /// * `ZX_OK` if the repository was added.
    /// * `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) -> (zx.status status);

    /// Remove a repository.
    ///
    /// Removing a repository will prevent future packages from being cached from this repository,
    /// but in-flight downloads may not be interrupted.
    ///
    /// Arguments:
    /// * `repo_url` is the URL of the repository we want to remove.
    ///
    /// Return Values:
    /// * `ZX_OK` if the repository was removed.
    /// * `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) -> (zx.status status);

    /// Add a mirror to a repository. This will overwrite the mirror if it already exists.
    ///
    /// Arguments:
    /// * `repo_url` is repository that corresponds with this mirror.
    /// * `mirror_url` is mirror URL to add to the resolver.
    ///
    /// Return Values:
    /// * `ZX_OK` if the mirror was removed.
    /// * `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) -> (zx.status status);

    /// Remove 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.
    ///
    /// Arguments:
    /// * `repo_url` the URL of the mirror's repository.
    /// * `mirror_url` the URL of the mirror we want to remove.
    ///
    /// Return Values:
    /// * `ZX_OK` if the mirror was removed.
    /// * `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) -> (zx.status status);

    /// Return an iterator over all repositories.
    ///
    /// Arguments:
    /// `iterator` is a request for an iterator.
    List(request<RepositoryIterator> iterator);
};

/// Describes the configuration necessary to connect to a repository and it's 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. 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;
};

/// Describes the keys used by the repository to authenticate it's packages.
///
/// The only supported algorithm at the moment is ed25519.
xunion RepositoryKeyConfig {
    /// The raw ed25519 public key as binary data.
    bytes ed25519_key;
};

/// Describes a key used to decrypt blobs.
///
/// The only supported algorithm at the moment is aes.
xunion RepositoryBlobKey {
    /// A raw aes key as binary data.
    bytes aes_key;
};

/// Describes 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;

    /// The private (or symmetric) key used to decrypt blobs fetched from this mirror. Optional.
    3: RepositoryBlobKey blob_key;

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

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