aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'proto/admin.proto')
-rw-r--r--proto/admin.proto341+341 −0
1 files changed, 341 insertions, 0 deletions
diff --git a/proto/admin.proto b/proto/admin.proto
new file mode 100644
--- /dev/null
+++ b/proto/admin.proto
@@ -0,0 +1,341 @@
+// Copyright (c) 2026 Nikolay Govorov
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+syntax = "proto3";
+
+package mirum;
+
+import "buf/validate/validate.proto";
+import "google/protobuf/timestamp.proto";
+
+option go_package = "dimidiumlabs/mirum/internal/protocol/pb";
+
+service Admin {
+ rpc UserCreate(UserCreateRequest) returns (UserCreateResponse);
+ rpc UserGet(UserGetRequest) returns (UserGetResponse);
+ rpc UserList(UserListRequest) returns (UserListResponse);
+ rpc UserUpdate(UserUpdateRequest) returns (UserUpdateResponse);
+ rpc UserDelete(UserDeleteRequest) returns (UserDeleteResponse);
+
+ rpc OrgCreate(OrgCreateRequest) returns (OrgCreateResponse);
+ rpc OrgGet(OrgGetRequest) returns (OrgGetResponse);
+ rpc OrgList(OrgListRequest) returns (OrgListResponse);
+ rpc OrgUpdate(OrgUpdateRequest) returns (OrgUpdateResponse);
+ rpc OrgDelete(OrgDeleteRequest) returns (OrgDeleteResponse);
+
+ rpc OrgMemberAdd(OrgMemberAddRequest) returns (OrgMemberAddResponse);
+ rpc OrgMemberGet(OrgMemberGetRequest) returns (OrgMemberGetResponse);
+ rpc OrgMemberList(OrgMemberListRequest) returns (OrgMemberListResponse);
+ rpc OrgMemberUpdate(OrgMemberUpdateRequest) returns (OrgMemberUpdateResponse);
+ rpc OrgMemberRemove(OrgMemberRemoveRequest) returns (OrgMemberRemoveResponse);
+
+ rpc WorkerCreate(WorkerCreateRequest) returns (WorkerCreateResponse);
+ rpc WorkerGet(WorkerGetRequest) returns (WorkerGetResponse);
+ rpc WorkerList(WorkerListRequest) returns (WorkerListResponse);
+ rpc WorkerDelete(WorkerDeleteRequest) returns (WorkerDeleteResponse);
+}
+
+// Common types
+
+enum Role {
+ ROLE_NONE = 0;
+ ROLE_OWNER = 1;
+ ROLE_ADMIN = 2;
+ ROLE_MEMBER = 3;
+}
+
+enum Perm {
+ PERM_NONE = 0;
+
+ PERM_USER_READ = 1;
+ PERM_USER_WRITE = 2;
+ PERM_USER_DELETE = 3;
+
+ PERM_ORG_READ = 4;
+ PERM_ORG_WRITE = 5;
+ PERM_ORG_DELETE = 6;
+ PERM_ORG_MEMBER_READ = 7;
+ PERM_ORG_MEMBER_WRITE = 8;
+
+ PERM_WORKER_READ = 9;
+ PERM_WORKER_WRITE = 10;
+}
+
+// ErrorInfo is attached as a ConnectError detail on every error.
+// The ConnectError message field is always empty — the server never sends
+// human-readable text. Clients switch on reason to select user-facing copy.
+message ErrorInfo {
+ ErrorReason reason = 1;
+
+ // Short stable identifiers for UI targeting (e.g. {"field": "slug"}).
+ // Never human-readable text.
+ map<string, string> metadata = 2;
+}
+
+enum ErrorReason {
+ ERROR_REASON_UNSPECIFIED = 0;
+ ERROR_REASON_INTERNAL = 1;
+
+ // Lookup failures
+ ERROR_REASON_USER_NOT_FOUND = 10;
+ ERROR_REASON_ORG_NOT_FOUND = 11;
+ ERROR_REASON_WORKER_NOT_FOUND = 12;
+ ERROR_REASON_MEMBER_NOT_FOUND = 13;
+
+ // Conflicts
+ ERROR_REASON_EMAIL_TAKEN = 20;
+ ERROR_REASON_SLUG_TAKEN = 21;
+ ERROR_REASON_ALREADY_MEMBER = 22;
+
+ // State preconditions
+ ERROR_REASON_LAST_OWNER = 30;
+ ERROR_REASON_SOLE_OWNER = 31;
+
+ // Validation
+ ERROR_REASON_INVALID_SLUG = 40;
+ ERROR_REASON_INVALID_ROLE = 41;
+ ERROR_REASON_RESERVED_EMAIL = 42;
+
+ // Auth
+ ERROR_REASON_UNAUTHENTICATED = 50;
+ ERROR_REASON_PERMISSION_DENIED = 51;
+ ERROR_REASON_INVALID_CREDENTIALS = 52;
+ ERROR_REASON_INVALID_CSRF = 53;
+
+ // Infrastructure
+ ERROR_REASON_RATE_LIMITED = 60;
+ ERROR_REASON_UNAVAILABLE = 61;
+ ERROR_REASON_UNIMPLEMENTED = 62;
+}
+
+message UserRef {
+ oneof ref {
+ option (buf.validate.oneof).required = true;
+ bytes id = 1 [(buf.validate.field).bytes = {
+ min_len: 16
+ max_len: 16
+ }];
+ string email = 2 [(buf.validate.field).string.email = true];
+ }
+}
+
+message OrgRef {
+ oneof ref {
+ option (buf.validate.oneof).required = true;
+ bytes id = 1 [(buf.validate.field).bytes = {
+ min_len: 16
+ max_len: 16
+ }];
+ string slug = 2 [(buf.validate.field).string = {
+ min_len: 2
+ max_len: 64
+ }];
+ }
+}
+
+message PageRequest {
+ bytes cursor = 1;
+ int32 page_size = 2;
+}
+message PageResponse {
+ bytes next_cursor = 1;
+ int32 total_count = 2;
+}
+
+// User management
+
+message User {
+ bytes id = 1;
+ string email = 2;
+ google.protobuf.Timestamp created_at = 3;
+}
+
+message UserCreateRequest {
+ string email = 1 [(buf.validate.field).string.email = true];
+ string password = 2 [(buf.validate.field).string.min_len = 1];
+}
+message UserCreateResponse {
+ bytes id = 1;
+}
+
+message UserGetRequest {
+ UserRef user = 1 [(buf.validate.field).required = true];
+}
+message UserGetResponse {
+ User user = 1;
+}
+
+message UserListRequest {
+ optional PageRequest page = 1;
+ optional string filter = 2;
+}
+message UserListResponse {
+ PageResponse page = 1;
+ repeated User users = 2;
+}
+
+message UserUpdateRequest {
+ UserRef user = 1 [(buf.validate.field).required = true];
+ optional string email = 2 [(buf.validate.field).string.email = true];
+ optional string password = 3 [(buf.validate.field).string.min_len = 1];
+}
+message UserUpdateResponse {}
+
+message UserDeleteRequest {
+ UserRef user = 1 [(buf.validate.field).required = true];
+}
+message UserDeleteResponse {}
+
+// Organization management
+
+message Org {
+ bytes id = 1;
+ string name = 2;
+ string slug = 3;
+ bool public = 4;
+ google.protobuf.Timestamp created_at = 5;
+}
+
+message OrgCreateRequest {
+ string name = 1 [(buf.validate.field).string.min_len = 1];
+ string slug = 2 [(buf.validate.field).string = {
+ min_len: 2
+ max_len: 64
+ }];
+ UserRef owner = 3 [(buf.validate.field).required = true];
+ bool public = 4;
+}
+message OrgCreateResponse {
+ bytes id = 1;
+}
+
+message OrgGetRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+}
+message OrgGetResponse {
+ Org org = 1;
+}
+
+message OrgListRequest {
+ optional PageRequest page = 1;
+ optional string filter = 2;
+}
+message OrgListResponse {
+ PageResponse page = 1;
+ repeated Org organizations = 2;
+}
+
+message OrgUpdateRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+ optional string name = 2 [(buf.validate.field).string.min_len = 1];
+ optional string slug = 3 [(buf.validate.field).string = {
+ min_len: 2
+ max_len: 64
+ }];
+ optional bool public = 4;
+}
+message OrgUpdateResponse {}
+
+message OrgDeleteRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+}
+message OrgDeleteResponse {}
+
+// Organization members
+
+message OrgMemberInfo {
+ User user = 1;
+ Role role = 2;
+ google.protobuf.Timestamp joined_at = 3;
+}
+
+message OrgMemberGetRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+ UserRef user = 2 [(buf.validate.field).required = true];
+}
+message OrgMemberGetResponse {
+ OrgMemberInfo member = 1;
+}
+
+message OrgMemberAddRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+ UserRef user = 2 [(buf.validate.field).required = true];
+ Role role = 3 [(buf.validate.field).enum = {
+ defined_only: true
+ not_in: [0]
+ }];
+}
+message OrgMemberAddResponse {}
+
+message OrgMemberListRequest {
+ optional PageRequest page = 1;
+ OrgRef org = 2 [(buf.validate.field).required = true];
+ optional string filter = 3;
+}
+message OrgMemberListResponse {
+ PageResponse page = 1;
+ repeated OrgMemberInfo members = 2;
+}
+
+message OrgMemberUpdateRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+ UserRef user = 2 [(buf.validate.field).required = true];
+ Role role = 3 [(buf.validate.field).enum = {
+ defined_only: true
+ not_in: [0]
+ }];
+}
+message OrgMemberUpdateResponse {}
+
+message OrgMemberRemoveRequest {
+ OrgRef org = 1 [(buf.validate.field).required = true];
+ UserRef user = 2 [(buf.validate.field).required = true];
+}
+message OrgMemberRemoveResponse {}
+
+// Worker management
+
+message Worker {
+ bytes id = 1;
+ bytes public_key = 2;
+ optional bytes org_id = 3;
+ google.protobuf.Timestamp created_at = 4;
+}
+
+message WorkerCreateRequest {
+ bytes public_key = 1 [(buf.validate.field).bytes = {
+ min_len: 32
+ max_len: 32
+ }];
+ optional OrgRef org = 2;
+}
+message WorkerCreateResponse {
+ bytes id = 1;
+}
+
+message WorkerGetRequest {
+ bytes id = 1 [(buf.validate.field).bytes = {
+ min_len: 16
+ max_len: 16
+ }];
+}
+message WorkerGetResponse {
+ Worker worker = 1;
+}
+
+message WorkerListRequest {
+ optional PageRequest page = 1;
+ optional string filter = 2;
+}
+message WorkerListResponse {
+ PageResponse page = 1;
+ repeated Worker workers = 2;
+}
+
+message WorkerDeleteRequest {
+ bytes id = 1 [(buf.validate.field).bytes = {
+ min_len: 16
+ max_len: 16
+ }];
+}
+message WorkerDeleteResponse {}