// 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.
flexible union 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.
flexible union 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);
};
