// 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 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, defaulting to 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, defaulting to 1.
    6: uint32 root_threshold;
};

/// 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.
    1: 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.
    1: 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);
};
