syntax = "proto3";
// holger.account.v1 — the repositories a person has here (2026-10-21, lane P4).
//
// The console is a thin layer: "My repositories" lists what this server says
// the signed-in person has, makes a private repository through this server,
// and shows the client setup this server writes for each one. The console
// keeps no owners, no permissions and no store; it renders these answers and
// the server's refusals as they are.
//
// Its own package, like holger.room.v1: holger.proto, and every downstream
// copy of it, does not move.
package holger.account.v1;
service AccountService {
// The repositories the caller has here: the ones made for them (they are the
// owner), and for an ADMIN of this server every repository but the estate's
// system ones. Anonymous: none, with the words to sign in. Never refused.
rpc MyRepositories(MyRepositoriesRequest) returns (MyRepositoriesReply);
// ADMIN of this server. Make a PRIVATE repository the caller owns, in one of
// the formats `MyRepositoriesReply.formats` names. Its reads need a
// credential of this server from the first request. The name is taken once:
// a name this server serves or has made is ALREADY_EXISTS; a name that is no
// repository name is INVALID_ARGUMENT; a format this server makes none of is
// FAILED_PRECONDITION. A twin, a growth or a read-only server refuses as
// every admin change does. The repository rides the twin and comes back with
// a recharge, as a sold one does.
rpc CreateRepository(CreateRepositoryRequest) returns (CreateRepositoryReply);
// **The owner grants or revokes** (lane P1): a named person (their name here, or their
// subject) may read, or read and write, one owner-only repository; `none` revokes. Its
// OWNER only, or an admin of this server; every change is audited. The person keeps no
// role elsewhere from it.
rpc Grant(GrantRequest) returns (GrantReply);
}
message GrantRequest {
string repository = 1;
// The person: their name on this server, or their subject (`passkey:…`).
string person = 2;
// `read`, `write` (read and write) or `none` (revoke).
string access = 3;
}
message GrantReply {
string repository = 1;
// Every grant the repository holds now.
repeated RepositoryGrant grants = 2;
// One sentence for the console.
string words = 3;
}
message RepositoryGrant {
// The person's name here (their subject when no name is known).
string person = 1;
string subject = 2;
// `read` or `write`.
string access = 3;
}
message MyRepositoriesRequest {}
message MyRepositoriesReply {
repeated MyRepository repositories = 1;
// The formats CreateRepository makes here for this caller ("cargo", "pip",
// "npm", "maven", "raw", "oci"). Empty: this caller makes none.
repeated string formats = 2;
// One sentence for the console to show as it is: who may make one, or why
// nothing is listed.
string words = 3;
}
message MyRepository {
string name = 1;
// The client's word for its format: "cargo", "pip", "npm", "maven", "raw",
// "oci", or the server's own type name for any other.
string format = 2;
// Its reads need a credential of this server.
bool private = 3;
// The principal it was made for; empty for the estate's own repositories and
// for a sale whose buyer has not registered yet.
string owner = 4;
// A door serves it now. False: it is made and is served from the next start
// (`words` says why).
bool served = 5;
// The client setup for this repository, written by this server.
repeated ClientSetup clients = 6;
// One sentence for the console to show as it is.
string words = 7;
// ── Its plan, as this server holds it (the ONE shop's signed fact) ──
// The plan's name; empty when nothing is bought for it (it is free).
string plan = 8;
// This server's word for where the plan stands: "free", "paid", "grace",
// "suspended", "retention", or "lapsed" (paid until a date that has passed,
// and no renewal has reached this server: uploads are refused until it is
// paid again).
string plan_state = 9;
// Paid until, Unix milliseconds; 0 when the fact names no date.
int64 paid_until_unix_ms = 10;
// One sentence for the console to show as it is, about the plan.
string plan_words = 11;
// The people its owner granted (lane P1): shown to its owner and to an admin only.
repeated RepositoryGrant grants = 12;
}
message ClientSetup {
// "cargo", "pip", "npm", "maven", "curl", "docker".
string client = 1;
// Where the snippet goes ("~/.cargo/config.toml"), or "shell".
string file = 2;
// The text, with YOUR-TOKEN where a token from My tokens goes.
string snippet = 3;
}
message CreateRepositoryRequest {
string name = 1;
// One of `MyRepositoriesReply.formats`.
string format = 2;
}
message CreateRepositoryReply {
MyRepository repository = 1;
// One sentence for the console to show as it is.
string words = 2;
}