104
interface/proto/forest/v1/organisations.proto
Normal file
104
interface/proto/forest/v1/organisations.proto
Normal file
@@ -0,0 +1,104 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package forest.v1;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message Organisation {
|
||||
string organisation_id = 1;
|
||||
string name = 2;
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
}
|
||||
|
||||
message CreateOrganisationRequest {
|
||||
string name = 1;
|
||||
}
|
||||
message CreateOrganisationResponse {
|
||||
string organisation_id = 1;
|
||||
}
|
||||
|
||||
message GetOrganisationRequest {
|
||||
oneof identifier {
|
||||
string organisation_id = 1;
|
||||
string name = 2;
|
||||
}
|
||||
}
|
||||
message GetOrganisationResponse {
|
||||
Organisation organisation = 1;
|
||||
}
|
||||
|
||||
message SearchOrganisationsRequest {
|
||||
string query = 1;
|
||||
int32 page_size = 2;
|
||||
string page_token = 3;
|
||||
}
|
||||
message SearchOrganisationsResponse {
|
||||
repeated Organisation organisations = 1;
|
||||
string next_page_token = 2;
|
||||
int32 total_count = 3;
|
||||
}
|
||||
|
||||
message ListMyOrganisationsRequest {
|
||||
// Optional role filter (e.g. "admin"); empty means all roles
|
||||
string role = 1;
|
||||
}
|
||||
message ListMyOrganisationsResponse {
|
||||
repeated Organisation organisations = 1;
|
||||
// The role the caller has in each organisation (parallel to organisations)
|
||||
repeated string roles = 2;
|
||||
}
|
||||
|
||||
// -- Members ------------------------------------------------------------------
|
||||
|
||||
message OrganisationMember {
|
||||
string user_id = 1;
|
||||
string username = 2;
|
||||
string role = 3;
|
||||
google.protobuf.Timestamp joined_at = 4;
|
||||
}
|
||||
|
||||
message AddMemberRequest {
|
||||
string organisation_id = 1;
|
||||
string user_id = 2;
|
||||
string role = 3;
|
||||
}
|
||||
message AddMemberResponse {
|
||||
OrganisationMember member = 1;
|
||||
}
|
||||
|
||||
message RemoveMemberRequest {
|
||||
string organisation_id = 1;
|
||||
string user_id = 2;
|
||||
}
|
||||
message RemoveMemberResponse {}
|
||||
|
||||
message UpdateMemberRoleRequest {
|
||||
string organisation_id = 1;
|
||||
string user_id = 2;
|
||||
string role = 3;
|
||||
}
|
||||
message UpdateMemberRoleResponse {
|
||||
OrganisationMember member = 1;
|
||||
}
|
||||
|
||||
message ListMembersRequest {
|
||||
string organisation_id = 1;
|
||||
int32 page_size = 2;
|
||||
string page_token = 3;
|
||||
}
|
||||
message ListMembersResponse {
|
||||
repeated OrganisationMember members = 1;
|
||||
string next_page_token = 2;
|
||||
int32 total_count = 3;
|
||||
}
|
||||
|
||||
service OrganisationService {
|
||||
rpc CreateOrganisation(CreateOrganisationRequest) returns (CreateOrganisationResponse);
|
||||
rpc GetOrganisation(GetOrganisationRequest) returns (GetOrganisationResponse);
|
||||
rpc SearchOrganisations(SearchOrganisationsRequest) returns (SearchOrganisationsResponse);
|
||||
rpc ListMyOrganisations(ListMyOrganisationsRequest) returns (ListMyOrganisationsResponse);
|
||||
rpc AddMember(AddMemberRequest) returns (AddMemberResponse);
|
||||
rpc RemoveMember(RemoveMemberRequest) returns (RemoveMemberResponse);
|
||||
rpc UpdateMemberRole(UpdateMemberRoleRequest) returns (UpdateMemberRoleResponse);
|
||||
rpc ListMembers(ListMembersRequest) returns (ListMembersResponse);
|
||||
}
|
||||
151
interface/proto/forest/v1/releases.proto
Normal file
151
interface/proto/forest/v1/releases.proto
Normal file
@@ -0,0 +1,151 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package forest.v1;
|
||||
|
||||
message AnnotateReleaseRequest {
|
||||
string artifact_id = 1;
|
||||
map<string, string> metadata = 2;
|
||||
Source source = 3;
|
||||
ArtifactContext context = 4;
|
||||
Project project = 5;
|
||||
Ref ref = 6;
|
||||
}
|
||||
message AnnotateReleaseResponse {
|
||||
Artifact artifact = 1;
|
||||
}
|
||||
|
||||
message GetArtifactBySlugRequest {
|
||||
string slug = 1;
|
||||
}
|
||||
message GetArtifactBySlugResponse {
|
||||
Artifact artifact = 1;
|
||||
}
|
||||
message GetArtifactsByProjectRequest {
|
||||
Project project = 1;
|
||||
}
|
||||
message GetArtifactsByProjectResponse {
|
||||
repeated Artifact artifact = 1;
|
||||
}
|
||||
|
||||
message ReleaseRequest {
|
||||
string artifact_id = 1;
|
||||
repeated string destinations = 2;
|
||||
repeated string environments = 3;
|
||||
}
|
||||
message ReleaseResponse {
|
||||
// List of release intents created (one per destination)
|
||||
repeated ReleaseIntent intents = 1;
|
||||
}
|
||||
|
||||
message ReleaseIntent {
|
||||
string release_intent_id = 1;
|
||||
string destination = 2;
|
||||
string environment = 3;
|
||||
}
|
||||
|
||||
message WaitReleaseRequest {
|
||||
string release_intent_id = 1;
|
||||
}
|
||||
|
||||
message WaitReleaseEvent {
|
||||
oneof event {
|
||||
ReleaseStatusUpdate status_update = 1;
|
||||
ReleaseLogLine log_line = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReleaseStatusUpdate {
|
||||
string destination = 1;
|
||||
string status = 2;
|
||||
}
|
||||
|
||||
message ReleaseLogLine {
|
||||
string destination = 1;
|
||||
string line = 2;
|
||||
string timestamp = 3;
|
||||
LogChannel channel = 4;
|
||||
}
|
||||
|
||||
enum LogChannel {
|
||||
LOG_CHANNEL_UNSPECIFIED = 0;
|
||||
LOG_CHANNEL_STDOUT = 1;
|
||||
LOG_CHANNEL_STDERR = 2;
|
||||
}
|
||||
|
||||
message GetOrganisationsRequest {}
|
||||
message GetOrganisationsResponse {
|
||||
repeated OrganisationRef organisations = 1;
|
||||
}
|
||||
|
||||
message GetProjectsRequest {
|
||||
oneof query {
|
||||
OrganisationRef organisation = 1;
|
||||
}
|
||||
}
|
||||
message GetProjectsResponse {
|
||||
repeated string projects = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
service ReleaseService {
|
||||
rpc AnnotateRelease(AnnotateReleaseRequest) returns (AnnotateReleaseResponse);
|
||||
rpc Release(ReleaseRequest) returns (ReleaseResponse);
|
||||
rpc WaitRelease(WaitReleaseRequest) returns (stream WaitReleaseEvent);
|
||||
|
||||
rpc GetArtifactBySlug(GetArtifactBySlugRequest) returns (GetArtifactBySlugResponse);
|
||||
rpc GetArtifactsByProject(GetArtifactsByProjectRequest) returns (GetArtifactsByProjectResponse);
|
||||
rpc GetOrganisations(GetOrganisationsRequest) returns (GetOrganisationsResponse);
|
||||
rpc GetProjects(GetProjectsRequest) returns (GetProjectsResponse);
|
||||
}
|
||||
|
||||
message Source {
|
||||
optional string user = 1;
|
||||
optional string email = 2;
|
||||
optional string source_type = 3;
|
||||
optional string run_url = 4;
|
||||
}
|
||||
|
||||
message ArtifactContext {
|
||||
string title = 1;
|
||||
optional string description = 2;
|
||||
optional string web = 3;
|
||||
optional string pr = 4;
|
||||
}
|
||||
|
||||
message Artifact {
|
||||
string id = 1;
|
||||
string artifact_id = 2;
|
||||
string slug = 3;
|
||||
map<string, string> metadata = 4;
|
||||
Source source = 5;
|
||||
ArtifactContext context = 6;
|
||||
Project project = 7;
|
||||
repeated ArtifactDestination destinations = 8;
|
||||
string created_at = 9;
|
||||
}
|
||||
|
||||
message ArtifactDestination {
|
||||
string name = 1;
|
||||
string environment = 2;
|
||||
string type_organisation = 3;
|
||||
string type_name = 4;
|
||||
uint64 type_version = 5;
|
||||
}
|
||||
|
||||
message Project {
|
||||
string organisation = 1;
|
||||
string project = 2;
|
||||
}
|
||||
|
||||
message Ref {
|
||||
string commit_sha = 1;
|
||||
optional string branch = 2;
|
||||
optional string commit_message = 3;
|
||||
optional string version = 4;
|
||||
optional string repo_url = 5;
|
||||
}
|
||||
|
||||
message OrganisationRef {
|
||||
string organisation = 1;
|
||||
}
|
||||
317
interface/proto/forest/v1/users.proto
Normal file
317
interface/proto/forest/v1/users.proto
Normal file
@@ -0,0 +1,317 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package forest.v1;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// UsersService handles user management, authentication, and profile operations.
|
||||
service UsersService {
|
||||
// Authentication
|
||||
rpc Register(RegisterRequest) returns (RegisterResponse);
|
||||
rpc Login(LoginRequest) returns (LoginResponse);
|
||||
rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse);
|
||||
rpc Logout(LogoutRequest) returns (LogoutResponse);
|
||||
|
||||
// User CRUD
|
||||
rpc GetUser(GetUserRequest) returns (GetUserResponse);
|
||||
rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse);
|
||||
rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse);
|
||||
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
|
||||
|
||||
// Password management
|
||||
rpc ChangePassword(ChangePasswordRequest) returns (ChangePasswordResponse);
|
||||
|
||||
// Email management
|
||||
rpc AddEmail(AddEmailRequest) returns (AddEmailResponse);
|
||||
rpc VerifyEmail(VerifyEmailRequest) returns (VerifyEmailResponse);
|
||||
rpc RemoveEmail(RemoveEmailRequest) returns (RemoveEmailResponse);
|
||||
|
||||
// Social / OAuth login
|
||||
rpc OAuthLogin(OAuthLoginRequest) returns (OAuthLoginResponse);
|
||||
rpc LinkOAuthProvider(LinkOAuthProviderRequest) returns (LinkOAuthProviderResponse);
|
||||
rpc UnlinkOAuthProvider(UnlinkOAuthProviderRequest) returns (UnlinkOAuthProviderResponse);
|
||||
|
||||
// Personal access tokens
|
||||
rpc CreatePersonalAccessToken(CreatePersonalAccessTokenRequest) returns (CreatePersonalAccessTokenResponse);
|
||||
rpc ListPersonalAccessTokens(ListPersonalAccessTokensRequest) returns (ListPersonalAccessTokensResponse);
|
||||
rpc DeletePersonalAccessToken(DeletePersonalAccessTokenRequest) returns (DeletePersonalAccessTokenResponse);
|
||||
|
||||
// Token introspection (requires valid access token)
|
||||
rpc TokenInfo(TokenInfoRequest) returns (TokenInfoResponse);
|
||||
|
||||
// MFA
|
||||
rpc SetupMfa(SetupMfaRequest) returns (SetupMfaResponse);
|
||||
rpc VerifyMfa(VerifyMfaRequest) returns (VerifyMfaResponse);
|
||||
rpc DisableMfa(DisableMfaRequest) returns (DisableMfaResponse);
|
||||
}
|
||||
|
||||
// ─── Core types ──────────────────────────────────────────────────────
|
||||
|
||||
message User {
|
||||
string user_id = 1; // UUID
|
||||
string username = 2;
|
||||
repeated UserEmail emails = 3;
|
||||
repeated OAuthConnection oauth_connections = 4;
|
||||
bool mfa_enabled = 5;
|
||||
google.protobuf.Timestamp created_at = 6;
|
||||
google.protobuf.Timestamp updated_at = 7;
|
||||
}
|
||||
|
||||
message UserEmail {
|
||||
string email = 1;
|
||||
bool verified = 2;
|
||||
}
|
||||
|
||||
enum OAuthProvider {
|
||||
OAUTH_PROVIDER_UNSPECIFIED = 0;
|
||||
OAUTH_PROVIDER_GITHUB = 1;
|
||||
OAUTH_PROVIDER_GOOGLE = 2;
|
||||
OAUTH_PROVIDER_GITLAB = 3;
|
||||
OAUTH_PROVIDER_MICROSOFT = 4;
|
||||
}
|
||||
|
||||
message OAuthConnection {
|
||||
OAuthProvider provider = 1;
|
||||
string provider_user_id = 2;
|
||||
string provider_email = 3;
|
||||
google.protobuf.Timestamp linked_at = 4;
|
||||
}
|
||||
|
||||
// ─── Authentication ──────────────────────────────────────────────────
|
||||
|
||||
message RegisterRequest {
|
||||
string username = 1;
|
||||
string email = 2;
|
||||
string password = 3;
|
||||
}
|
||||
|
||||
message RegisterResponse {
|
||||
User user = 1;
|
||||
AuthTokens tokens = 2;
|
||||
}
|
||||
|
||||
message LoginRequest {
|
||||
// Login with either username or email
|
||||
oneof identifier {
|
||||
string username = 1;
|
||||
string email = 2;
|
||||
}
|
||||
string password = 3;
|
||||
}
|
||||
|
||||
message LoginResponse {
|
||||
User user = 1;
|
||||
AuthTokens tokens = 2;
|
||||
}
|
||||
|
||||
message RefreshTokenRequest {
|
||||
string refresh_token = 1;
|
||||
}
|
||||
|
||||
message RefreshTokenResponse {
|
||||
AuthTokens tokens = 1;
|
||||
}
|
||||
|
||||
message LogoutRequest {
|
||||
string refresh_token = 1;
|
||||
}
|
||||
|
||||
message LogoutResponse {}
|
||||
|
||||
message AuthTokens {
|
||||
string access_token = 1;
|
||||
string refresh_token = 2;
|
||||
int64 expires_in_seconds = 3;
|
||||
}
|
||||
|
||||
// ─── Token introspection ─────────────────────────────────────────────
|
||||
|
||||
message TokenInfoRequest {}
|
||||
|
||||
message TokenInfoResponse {
|
||||
string user_id = 1;
|
||||
int64 expires_at = 2; // Unix timestamp (seconds)
|
||||
}
|
||||
|
||||
// ─── User CRUD ───────────────────────────────────────────────────────
|
||||
|
||||
message GetUserRequest {
|
||||
oneof identifier {
|
||||
string user_id = 1;
|
||||
string username = 2;
|
||||
string email = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message GetUserResponse {
|
||||
User user = 1;
|
||||
}
|
||||
|
||||
message UpdateUserRequest {
|
||||
string user_id = 1;
|
||||
optional string username = 2;
|
||||
}
|
||||
|
||||
message UpdateUserResponse {
|
||||
User user = 1;
|
||||
}
|
||||
|
||||
message DeleteUserRequest {
|
||||
string user_id = 1;
|
||||
}
|
||||
|
||||
message DeleteUserResponse {}
|
||||
|
||||
message ListUsersRequest {
|
||||
int32 page_size = 1;
|
||||
string page_token = 2;
|
||||
optional string search = 3; // search across username, email
|
||||
}
|
||||
|
||||
message ListUsersResponse {
|
||||
repeated User users = 1;
|
||||
string next_page_token = 2;
|
||||
int32 total_count = 3;
|
||||
}
|
||||
|
||||
// ─── Password management ─────────────────────────────────────────────
|
||||
|
||||
message ChangePasswordRequest {
|
||||
string user_id = 1;
|
||||
string current_password = 2;
|
||||
string new_password = 3;
|
||||
}
|
||||
|
||||
message ChangePasswordResponse {}
|
||||
|
||||
// ─── Email management ────────────────────────────────────────────────
|
||||
|
||||
message AddEmailRequest {
|
||||
string user_id = 1;
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
message AddEmailResponse {
|
||||
UserEmail email = 1;
|
||||
}
|
||||
|
||||
message VerifyEmailRequest {
|
||||
string user_id = 1;
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
message VerifyEmailResponse {}
|
||||
|
||||
message RemoveEmailRequest {
|
||||
string user_id = 1;
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
message RemoveEmailResponse {}
|
||||
|
||||
// ─── OAuth / Social login ────────────────────────────────────────────
|
||||
|
||||
message OAuthLoginRequest {
|
||||
OAuthProvider provider = 1;
|
||||
string authorization_code = 2;
|
||||
string redirect_uri = 3;
|
||||
}
|
||||
|
||||
message OAuthLoginResponse {
|
||||
User user = 1;
|
||||
AuthTokens tokens = 2;
|
||||
bool is_new_user = 3;
|
||||
}
|
||||
|
||||
message LinkOAuthProviderRequest {
|
||||
string user_id = 1;
|
||||
OAuthProvider provider = 2;
|
||||
string authorization_code = 3;
|
||||
string redirect_uri = 4;
|
||||
}
|
||||
|
||||
message LinkOAuthProviderResponse {
|
||||
OAuthConnection connection = 1;
|
||||
}
|
||||
|
||||
message UnlinkOAuthProviderRequest {
|
||||
string user_id = 1;
|
||||
OAuthProvider provider = 2;
|
||||
}
|
||||
|
||||
message UnlinkOAuthProviderResponse {}
|
||||
|
||||
// ─── Personal access tokens ──────────────────────────────────────────
|
||||
|
||||
message PersonalAccessToken {
|
||||
string token_id = 1; // UUID
|
||||
string name = 2;
|
||||
repeated string scopes = 3;
|
||||
google.protobuf.Timestamp expires_at = 4;
|
||||
google.protobuf.Timestamp last_used = 5;
|
||||
google.protobuf.Timestamp created_at = 6;
|
||||
}
|
||||
|
||||
message CreatePersonalAccessTokenRequest {
|
||||
string user_id = 1;
|
||||
string name = 2;
|
||||
repeated string scopes = 3;
|
||||
// Duration in seconds; 0 = no expiry
|
||||
int64 expires_in_seconds = 4;
|
||||
}
|
||||
|
||||
message CreatePersonalAccessTokenResponse {
|
||||
PersonalAccessToken token = 1;
|
||||
// The raw token value, only returned on creation
|
||||
string raw_token = 2;
|
||||
}
|
||||
|
||||
message ListPersonalAccessTokensRequest {
|
||||
string user_id = 1;
|
||||
}
|
||||
|
||||
message ListPersonalAccessTokensResponse {
|
||||
repeated PersonalAccessToken tokens = 1;
|
||||
}
|
||||
|
||||
message DeletePersonalAccessTokenRequest {
|
||||
string token_id = 1;
|
||||
}
|
||||
|
||||
message DeletePersonalAccessTokenResponse {}
|
||||
|
||||
// ─── MFA ─────────────────────────────────────────────────────────────
|
||||
|
||||
enum MfaType {
|
||||
MFA_TYPE_UNSPECIFIED = 0;
|
||||
MFA_TYPE_TOTP = 1;
|
||||
}
|
||||
|
||||
message SetupMfaRequest {
|
||||
string user_id = 1;
|
||||
MfaType mfa_type = 2;
|
||||
}
|
||||
|
||||
message SetupMfaResponse {
|
||||
string mfa_id = 1; // UUID
|
||||
// TOTP provisioning URI (otpauth://...)
|
||||
string provisioning_uri = 2;
|
||||
// Base32-encoded secret for manual entry
|
||||
string secret = 3;
|
||||
}
|
||||
|
||||
message VerifyMfaRequest {
|
||||
string mfa_id = 1;
|
||||
// The TOTP code to verify setup
|
||||
string code = 2;
|
||||
}
|
||||
|
||||
message VerifyMfaResponse {}
|
||||
|
||||
message DisableMfaRequest {
|
||||
string user_id = 1;
|
||||
// Current TOTP code to confirm disable
|
||||
string code = 2;
|
||||
}
|
||||
|
||||
message DisableMfaResponse {}
|
||||
Reference in New Issue
Block a user