Source
- acme
- user
- v1
user.proto
proto3 · package acme.user.v1
1
syntax = "proto3";3
// User accounts and profile data for the Acme identity platform.4
//5
// ## In this package6
//7
// | Type | Purpose |8
// | --- | --- |9
// | [User](../../messages/acme.user.v1.User/) | Identity, lifecycle, and profile data. |10
// | [Address](../../messages/acme.user.v1.Address/) | Postal and billing details. |11
// | [UserState](../../enums/acme.user.v1.UserState/) | Account lifecycle values. |12
// | [UserService](../../services/acme.user.v1.UserService/) | Read, list, create, and watch accounts. |13
//14
// ## Getting started15
//16
// 1. Read the User page for a JSON example and field validation rules.17
// 2. Follow UserService to inspect request types and HTTP bindings.18
// 3. Explore [v2 sessions](../acme.user.v2/) to see this account schema reused.19
//20
// > **Shared types:** the session API imports the v1 User definition rather21
// > than duplicating account fields in another version.22
package acme.user.v1;24
import "acme/security/options.proto";25
import "buf/validate/validate.proto";26
import "google/api/field_behavior.proto";27
import "google/protobuf/timestamp.proto";29
option go_package = "acme.example/user/v1;userv1";30
option java_package = "com.acme.user.v1";31
option (acme.security.owner) = "identity-platform";33
// Lifecycle state of a user account.34
//35
// ## State guide36
//37
// | Value | Meaning |38
// | --- | --- |39
// | `USER_STATE_UNSPECIFIED` | No lifecycle state has been supplied. |40
// | `USER_STATE_ACTIVE` | The account is active. |41
// | `USER_STATE_SUSPENDED` | The account is suspended. |42
// | `USER_STATE_DELETED` | Deprecated; retained for compatibility. |43
enum UserState {44
USER_STATE_UNSPECIFIED = 0;45
USER_STATE_ACTIVE = 1;46
USER_STATE_SUSPENDED = 2;47
USER_STATE_DELETED = 3 [deprecated = true];48
}50
// Postal or billing address nested on a user.51
message Address {52
string line1 = 1 [(buf.validate.field).string.min_len = 1];53
string line2 = 2;54
string city = 3;55
string region = 4;56
string postal_code = 5;57
string country_code = 6 [(buf.validate.field).string = { min_len: 2, max_len: 2 }];58
}60
// A user account in the Acme identity platform.61
//62
// Users are the primary subject of authentication, billing, and support63
// workflows. Changing the shape of this message is a PACKAGE-breaking change.64
//65
// ## Reading a user66
//67
// - **Identity:** `id` is a stable UUID; `email` is the required login address.68
// - **Lifecycle:** `state`, `created_at`, and `updated_at` describe the account.69
// - **Profile:** `display_name`, `nickname`, and `preferences` hold presentation70
// choices. Postal details use the [Address message](../acme.user.v1.Address/).71
//72
// ## Example JSON73
//74
// This response uses the [ProtoJSON mapping](https://protobuf.dev/programming-guides/json/):75
// field names become lower camel case and enum values remain strings.76
//77
// ```json78
// {79
// "id": "550e8400-e29b-41d4-a716-446655440000",80
// "email": "alex@example.com",81
// "displayName": "Alex Chen",82
// "state": "USER_STATE_ACTIVE",83
// "createdAt": "2026-01-15T09:30:00Z",84
// "preferences": {85
// "marketingOptIn": false,86
// "locale": "en-GB",87
// "timeZone": "Europe/London"88
// }89
// }90
// ```91
//92
// ## Creating an account93
//94
// 1. Set the required `email` and choose a `display_name` of 1 to 80 characters.95
// 2. Add profile preferences or up to five postal addresses as needed.96
// 3. Omit the output-only `id`, `created_at`, and `updated_at` fields from input.97
//98
// > **Privacy:** email and phone fields carry PII annotations. Their masking99
// > and hashing policies describe how consumers should handle sensitive data;100
// > the schema itself does not redact values.101
message User {102
option (acme.security.audit_required) = true;104
reserved 3, 15 to 20;105
reserved "legacy_id";107
// Stable identifier. Never reused.108
string id = 1 [109
(google.api.field_behavior) = IDENTIFIER,110
(google.api.field_behavior) = OUTPUT_ONLY,111
(buf.validate.field).string.uuid = true112
];114
// Login email. **PII:** follow the `identity/email` masking policy.115
string email = 2 [116
(google.api.field_behavior) = REQUIRED,117
(acme.security.pii) = {118
sensitive: true119
redaction: REDACTION_MASK120
policy: "identity/email"121
},122
(buf.validate.field).string.email = true123
];125
string display_name = 4 [126
(buf.validate.field).string = { min_len: 1, max_len: 80 }127
];129
optional string nickname = 5;131
UserState state = 6;133
google.protobuf.Timestamp created_at = 7 [134
(google.api.field_behavior) = OUTPUT_ONLY135
];137
google.protobuf.Timestamp updated_at = 8 [138
(google.api.field_behavior) = OUTPUT_ONLY139
];141
// An optional contact channel in addition to the login email.142
//143
// - `phone` carries the `identity/phone` hashing policy.144
// - `pager` is **deprecated** and remains only for compatibility.145
//146
// A `oneof` can contain at most one of these values at a time.147
oneof contact {148
string phone = 9 [149
(acme.security.pii) = {150
sensitive: true151
redaction: REDACTION_HASH152
policy: "identity/phone"153
}154
];155
string pager = 10 [deprecated = true];156
}158
map<string, string> labels = 11;160
repeated Address addresses = 12 [(buf.validate.field).repeated.max_items = 5];162
// Nested profile preferences.163
//164
// ### Example choices165
//166
// | Field | Example | Purpose |167
// | --- | --- | --- |168
// | `marketing_opt_in` | `false` | Marketing preference. |169
// | `locale` | `en-GB` | Language and regional formatting. |170
// | `time_zone` | `Europe/London` | Local time presentation. |171
//172
// These strings have no validation rules in this example schema.173
message Preferences {174
bool marketing_opt_in = 1;175
string locale = 2;176
string time_zone = 3;177
}179
Preferences preferences = 13;180
}182
message GetUserRequest {183
string id = 1 [184
(google.api.field_behavior) = REQUIRED,185
(buf.validate.field).string.uuid = true186
];187
}189
message GetUserResponse {190
User user = 1;191
}193
message ListUsersRequest {194
int32 page_size = 1 [(buf.validate.field).int32 = { gte: 0, lte: 100 }];195
string page_token = 2;196
string filter = 3;197
}199
message ListUsersResponse {200
repeated User users = 1;201
string next_page_token = 2;202
}204
message CreateUserRequest {205
User user = 1 [(google.api.field_behavior) = REQUIRED];206
}208
message CreateUserResponse {209
User user = 1;210
}