Access Control Protobuf (Documents v3alpha)

    Overview

    This document specifies the AccessControl gRPC service for managing object‑capability style permissions in Seed Documents. It enables callers to create and enumerate delegation tokens (Capabilities) that grant roles over paths within an Account’s document namespace. The API is designed for auditability and safe, incremental delegation (including nested delegations) while avoiding circular dependencies with other services.

    Goals

      First‑class, typed representation of Capabilities as unforgeable tokens authorizing actions on a path within an account.

      Read APIs to list capabilities (by account/path and by delegate) with pagination.

      A write API to create (issue) capabilities with explicit constraints (role, recursive vs. exact path).

      Clear semantics for nested delegation (no privilege escalation above ancestors).

    Non‑Goals

      Implementing full revocation workflows (future RevokeCapability).

      Managing user/group memberships or identity issuance (see Identity/Accounts services).

      Evaluating authorization on every resource method—this API manages tokens; enforcement happens elsewhere.

    Protocol Definition

      syntax = "proto3";
      
      package com.seed.documents.v3alpha;
      
      import "google/protobuf/timestamp.proto";
      
      option go_package = "seed/backend/genproto/documents/v3alpha;documents";
      
      // Access Control service provides management API for issuing and revoking Capabilities.
      service AccessControl {
        // Lists existing capabilities.
        rpc ListCapabilities(ListCapabilitiesRequest) returns (ListCapabilitiesResponse);
      
        // List capabilities for a specific delegate.
        rpc ListCapabilitiesForDelegate(ListCapabilitiesForDelegateRequest) returns (ListCapabilitiesResponse);
      
        // Creates a new capability.
        rpc CreateCapability(CreateCapabilityRequest) returns (Capability);
      
        // Get a single capability by ID.
        rpc GetCapability(GetCapabilityRequest) returns (Capability);
      
        // TODO: implement capability revocation.
        //
        // rpc RevokeCapability(RevokeCapabilityRequest) returns (Revocation);
      }
      
      // Request to list capabilities.
      message ListCapabilitiesRequest {
        // Required. Account for which to list the capabilities.
        string account = 1;
      
        // Required. Path within the account to list the capabilities for.
        // Empty string means root document.
        // String "*" means all documents.
        string path = 2;
      
        // Optional. By default all capabilities that match the path are returned,
        // even if they were issued for some parent path.
        // If this field is true, only capabilities that match the path exactly are returned.
        bool ignore_inherited = 3;
      
        // Optional. Number of capabilities to return in the response.
        int32 page_size = 4;
      
        // Optional. Page token to continue listing capabilities.
        string page_token = 5;
      }
      
      // Response to list capabilities.
      message ListCapabilitiesResponse {
        // List of capabilities.
        repeated Capability capabilities = 1;
      
        // Token for the next page, if any.
        string next_page_token = 2;
      }
      
      // Request to list capabilities for a specific delegate.
      message ListCapabilitiesForDelegateRequest {
        // The public key of the delegate to list capabilities for.
        string delegate = 1;
      
        // Optional. Number of capabilities to return in the response.
        int32 page_size = 2;
      
        // Optional. Page token to continue listing capabilities.
        string page_token = 3;
      }
      
      // Request to create a new capability.
      message CreateCapabilityRequest {
        // Required. Name of the key to use for signing the capability.
        string signing_key_name = 1;
      
        // Required. Account ID to which this capability is delegated.
        string delegate = 2;
      
        // Required. Account ID to which this capability gives access.
        string account = 3;
      
        // Required. Path within the account that this capability grants access to.
        // Empty string means root document.
        string path = 4;
      
        // Required. Role that this capability grants to the delegate.
        // If capability is nested, the role cannot be higher than the role of any ancestor capability.
        Role role = 5;
      
        // Optional. By default capabilities give access to the path recursively.
        // This flag can be used to restrict the capability only to specific path.
        bool no_recursive = 6;
      
        // Optional. Short, user-provided label for the capability for user's convenience to identify them later.
        // The label is public and cannot be changed.
        string label = 7;
      }
      
      // Request to get a single capability.
      message GetCapabilityRequest {
        // Required. ID of the capability to get.
        string id = 1;
      }
      
      // Capability is an unforgeable token that grants access to a specific path within an account.
      message Capability {
        // ID of this capability.
        string id = 1;
      
        // ID of the account that issued the capability.
        string issuer = 2;
      
        // ID of the account that the capability is delegated to.
        string delegate = 3;
      
        // Account ID that capability grants access to.
        // This is the same as issuer when it's a first-grade capability,
        // but issuer can be different if the capability is delegated further down.
        string account = 4;
      
        // Path within the account which the capability grants access to.
        string path = 5;
      
        // Role that the capability grants to the delegate.
        Role role = 6;
      
        // Normally capabilities are applied recursively (i.e. path + all the subpaths),
        // but it can be limited to only to the exact path match.
        bool is_exact = 7;
      
        // Timestamp when this capability was issued.
        google.protobuf.Timestamp create_time = 8;
      
        // Optional. Short, user-provided label for the capability for user's convenience to identify different capabilities.
        string label = 9;
      }
      
      enum Role {
        // Invalid default value.
        ROLE_UNSPECIFIED = 0;
      
        // TODO: Implement the editor role.
        //
        // EDITOR = 1;
      
        // Has write access to the document
        WRITER = 2;
      
        // Grants full authority over the key,
        // including the idea to act on behalf of the issuing key.
        AGENT = 3;
      }