Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 25 additions & 154 deletions doc/index.html

Large diffs are not rendered by default.

205 changes: 205 additions & 0 deletions findings.md
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed, only for reference

Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Proto API Findings

Prompt: please identify inconsistencies and logical problems and write them into findings.md

This document captures inconsistencies and logical problems identified across the proto API definitions.

---

## 1. Comment Mismatches with Field / Message Purpose

### C1. partition.proto - "Meta for this ip" on Partition message (line 27)✅

```
// Meta for this ip
Meta meta = 2;
```

The field belongs to the `Partition` message but the comment says "ip". Should be "Meta for this partition".

### C2. partition.proto - "Ip the partition" on PartitionServiceGetResponse (line 87)✅

```
// Ip the partition
Machine machine = 1;
```
Comment says "Ip" instead of "Partition".

### C3. partition.proto - "Ips the partitions" on PartitionServiceListResponse (line 92)✅
```
// Ips the partitions
repeated Machine machines = 1;
```
Comment says "Ips" instead of "Partitions".

### C4. image.proto - Multiple wrong references ("imageLayout" and "ip")✅
- Line 70: `// Id of this imageLayout` should say "this image"
- Line 73: `// Meta for this ip` should say "this image"
- Lines 76-78: `// Name of this imageLayout` and `// Description of this imageLayout` should say "this image"

### C5. project.proto - Delete and Update request comments say "to get"✅
- Line 191 (`ProjectServiceDeleteRequest`, `uuid` field): `// Project is the uuid of the project to get` should say "to delete"
- Line 203 (`ProjectServiceUpdateRequest`, `uuid` field): same comment, should say "to update"

### C6. version.proto comments (lines 22-27) - Validation misuse
All four fields (`version`, `revision`, `git_sha1`, `build_date`) use `is_description` which is semantically wrong. These are structured data (semantic version, revision, git SHA1, build date), not free-form description text.

### C7. machine.proto - `firewall_spec` non-optional with conditional comment
- Line 147-148: `FirewallSpec firewall_spec = 18;` is non-optional, but the comment says `"if allocationType is firewall"`. Since it's not optional, an empty `FirewallSpec` is always sent regardless of `allocation_type`, making the conditional comment misleading.

### C8. response messages say "request payload"✅
All machine response messages incorrectly say "request payload" in their comments:
- `MachineServiceGetResponse` (line 73): "request payload" → "response payload"
- `MachineServiceCreateResponse` (line 158): same
- `MachineServiceUpdateResponse` (line 198): same
- `MachineServiceListResponse` (line 212): same
- `MachineServiceDeleteResponse` (line 226): same
- Same pattern in admin/v2/machine.proto lines 57 and 72

### C9. machine.proto - "deleteds" typo (line 228)✅
```
// Machine which was deleteds
```

### C10. common.proto - "Labels consists labels" (line 125)
```
// Labels consists labels
```

### C11. common.proto - "infra role" vs "machine role" (line 104)✅
```
// MachineRole are used to define which infra role a microservice must provide to call this method
```
Should say "which **machine** role" since the extension is for `MachineRole`.

### C12. project.proto - Wrong type in comment (line 232)✅
```
// ProjectServiceInviteRequest is the response payload to a invite member request
```
Comment says "ProjectServiceInviteRequest" but this is the `InviteResponse` message.

### C13. project.proto - Wrong type in comment (line 306)✅
```
// ProjectServiceInvitesListResponse is the response payload to a accept invite request
```
Comment says "InvitesListResponse" but this is the `InviteAcceptResponse` message.

### C14. tenant.proto - Wrong type in comment (line 292)✅
```
// TenantServiceInvitesListResponse is the response payload to a accept invite request
```
Same issue as C13.

### C15. ip.proto - Awkward comment (lines 121-122)✅
```
// Ip the ip to update
```
Should read "ID of the IP to update" or "IP address to update".

### C16. machine.proto - "overrules" nonstandard word (line 85)✅
```
// this field overrules size and partition.
```
Should be "overrides" or "takes precedence over".

### C17. admin/v2/machine.proto - Grammar errors (line 105)✅
```
// Query to list one ore more bmcs of more machines
```
"ore" → "or", "many machines" likely intended instead of "more machines".

### C18. machine.proto - "store" should be "stored" (lines 112, 178, 332)✅
```
// At most 50 keys can be store.
```
Should be "stored".

### C19. predefined_rules.proto - "macadress" typo (line 11)✅
Missing second "s": should be "macaddress".

---

## 2. Validation Rule Misuse

### V1. machine.proto - BMC fields use `is_description` (lines 279-287)
`MachineBMC` has six fields (`user`, `password`, `interface`, `version`, `power_state`, `address`) all validated with `is_description` (a rule meaning `size() <= 256`). This is wrong:
- `user` (BMC username) should use `is_name` or a dedicated username rule
- `password` should use min/max length validation
- `interface` should use a network interface name validation rule
- `version` should use a version-like pattern validation
- `power_state` should have a reasonable length constraint
- `address` at line 289 already uses `host_and_port` which is correct — only 5 of 6 fields are misvalidated

### V2. machine.proto - BIOS fields use `is_description` (lines 579-581)
`MachineBios` fields `version`, `vendor`, and `date` all use `is_description`. These are BIOS identifiers, not descriptions.

### V3. machine.proto - FRU fields all use `is_description` (lines 593-607)
All eight fields in `MachineFRU` (`chassis_part_number`, `chassis_part_serial`, `board_mfg`, `board_mfg_serial`, `board_part_number`, `product_manufacturer`, `product_part_number`, `product_serial`) use `is_description`. These are FRU identifiers.

### V4. machine.proto - version.proto style issues
Same systematic misuse of `is_description` as in V1 above, applied to BIOS and FRU hardware identifiers that are structured data, not free-form descriptions.

### V5. v2/size_imageconstraint.proto - semver_match uses `is_description` (lines 57-58)
```
string semver_match = 2 [(buf.validate.field).string.(metalstack.api.v2.is_description) = true];
```
A semver match string (e.g., `">= 20.04.20211011"`) is structured data, not a description.

### V6. admin/v2/switch.proto - Wrong rules (lines 100, 102)
- `management_user` uses `is_name` (likely wrong for a username, should use a dedicated username rule)
- `console_command` uses `is_description` (should use command-line validation)

---

## 3. Validation Gaps

### G1. vpn.proto - No validation on VPNNode (lines 15-22)✅
```
message VPNNode {
uint64 id = 1;
string name = 2;
string project = 3;
repeated string ip_addresses = 4;
google.protobuf.Timestamp last_seen = 5;
bool online = 6;
}
```
At minimum, `name` should use `is_name` and `ip_addresses` should be validated for proper IP format.

### G2. partition.proto - Boot commandline has no validation (line 57) ✅
```
string commandline = 3;
```
Kernel command lines can be long and should have max length validation.

---

## 4. Functional Inconsistencies

### F1. BMC query cannot search by hostname
- `MachineBMC.address` (machine.proto line 495): uses `host_and_port` (accepts `<ip>:<port>` or `<hostname>:<port>`)
- `MachineBMCQuery.address` (machine.proto line 507): uses `ip` only (pure IP addresses)

This means you can store and use a BMC with a hostname, but you **cannot query** by that hostname. The query only matches IP addresses, making hostname-based BMC lookup impossible.

### F2. Duplicate `MachineProvisioningEvent` definitions ✅
Two completely separate definitions exist with identical structure:
- `metalstack.api.v2.MachineProvisioningEvent` (machine.proto line 690)
- `metalstack.infra.v2.MachineProvisioningEvent` (infra/v2/event.proto line 33)

Both have enums with identical values ("Alive", "Crashed", "PXE Booting", etc.) but different enum name prefixes. The infra/event.proto does not import machine.proto — it duplicates everything. Risk of drift.

---

## 5. Cross-Version Inconsistencies

### X1. Partition `min_items` missing in admin update
- `api/v2/size_reservation.proto` (SizeReservation): partitions have `min_items: 1` — at least one required
- `admin/v2/size_reservation.proto` (SizeReservationServiceUpdateRequest): partitions at field 5 is **missing** `min_items: 1`, allowing empty partitions in updates

---

## 6. Naming Pattern Inconsistencies in filesystem.proto

### N1. `MatchMachine` message confusing naming
The message `MatchMachine` at line 73 has a field called `filesystem_layout` which is a string parameter, but the oneof case name is `machine_and_filesystemlayout`. The naming is inconsistent — the message name and field name don't clearly communicate what this match operation does.
19 changes: 10 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.26
require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1
buf.build/go/protovalidate v1.2.0
connectrpc.com/connect v1.19.2
connectrpc.com/connect v1.20.0
github.com/bufbuild/protocompile v0.14.1
github.com/go-task/slim-sprig/v3 v3.0.0
github.com/golang-jwt/jwt/v5 v5.3.1
Expand All @@ -17,19 +17,20 @@ require (
)

require (
cel.dev/expr v0.25.1 // indirect
cel.dev/expr v0.25.2 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/cel-go v0.28.0 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/google/cel-go v0.28.1 // indirect
github.com/klauspost/compress v1.18.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/minio/minlz v1.1.0 // indirect
github.com/minio/minlz v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.3 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/text v0.36.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect
golang.org/x/text v0.37.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260523011958-0a33c5d7ca68 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
38 changes: 18 additions & 20 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1 h1:s6hzCXtND/ICdGPTMGk7C+/BFlr2Jg5GyH0NKf4XGXg=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM=
buf.build/go/protovalidate v1.1.3 h1:m2GVEgQWd7rk+vIoAZ+f0ygGjvQTuqPQapBBdcpWVPE=
buf.build/go/protovalidate v1.1.3/go.mod h1:9XIuohWz+kj+9JVn3WQneHA5LZP50mjvneZMnbLkiIE=
buf.build/go/protovalidate v1.2.0 h1:DQVrUWkmGTBij+kOYv/x2LLxwcLaGKMdzShj1/6/3H0=
buf.build/go/protovalidate v1.2.0/go.mod h1:7rYiQEhqvAipoazpVNBBH2S2f8bjG4huMVy1V2Yofn4=
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ=
connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4=
Expand All @@ -21,14 +19,14 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/cel-go v0.28.0 h1:KjSWstCpz/MN5t4a8gnGJNIYUsJRpdi/r97xWDphIQc=
github.com/google/cel-go v0.28.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8=
github.com/google/cel-go v0.28.1 h1:YWIwi77J4xIsYUwAF/iIuS6haffzIHS8yWI8glSbLWM=
github.com/google/cel-go v0.28.1/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/connect-compress/v2 v2.1.1 h1:ycZNp4rWOZBodVE2Ls5AzK4aHkyK+GteEfzRZgKNs+c=
github.com/klauspost/connect-compress/v2 v2.1.1/go.mod h1:9oilsPHJMzGKkjafSBk9J7iVo4mO+dw0G0KSdVpnlVE=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
Expand All @@ -38,8 +36,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/minio/minlz v1.1.0 h1:rUOGu3EP4EqJC5k3qCsIwEnZiJULKqtRyDdqbhlvMmQ=
github.com/minio/minlz v1.1.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/minio/minlz v1.1.1 h1:OGmft1V6AnI/Wme332U6bhG54nxEan+VFgkD7lat4KM=
github.com/minio/minlz v1.1.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand All @@ -53,14 +51,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 h1:zUWMZsvo/IJcD1t6MNCPO/azZTwz0TvwCBqr5aifoVY=
google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529/go.mod h1:a5OGAgyRr4lqco7AG9hQM9Fwh0N2ZV4grR0eXFEsXQg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw=
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
google.golang.org/genproto/googleapis/api v0.0.0-20260523011958-0a33c5d7ca68 h1:WVVw1Nl19li0fMX++FJ3ye1z9+S1N35QODDy5qpnaXw=
google.golang.org/genproto/googleapis/api v0.0.0-20260523011958-0a33c5d7ca68/go.mod h1:1dCETSCY2YKZNXQE3h4fun3TYwF5p8jejRKZgfWAgAY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 h1:PvEgGJf9C/1u5CHkInMg7UFYYUoiaQmW2LbtH0pjB78=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
6 changes: 3 additions & 3 deletions go/metalstack/admin/v2/machine.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion go/metalstack/api/v2/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions go/metalstack/api/v2/image.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading