From 117c4c66883438090309bdde5e680e1ca0c23d95 Mon Sep 17 00:00:00 2001 From: crisfiorini-oss Date: Thu, 29 Oct 2026 14:55:38 +0000 Subject: [PATCH 1/2] fix: refresh authenticated module viewer request bindings --- .gitattributes | 1 + CHANGELOG.md | 7 + README.md | 14 +- SOURCE.txt | 6 +- buf.gen.yaml | 5 +- gen/host/installation/v1/installation.pb.go | 1873 +++++++++++++++++ .../installation.connect.go | 516 +++++ .../installations.connect.go | 18 +- .../work_contexts.connect.go | 53 + gen/saas/accounts/v1/datasource.pb.go | 34 +- gen/saas/accounts/v1/installations.pb.go | 137 +- .../accounts/v1/module_capabilities.pb.go | 60 +- gen/saas/accounts/v1/work_contexts.pb.go | 79 +- .../v1/workload_operation_admission.pb.go | 340 +++ gen/saas/catalog/v1/catalog.pb.go | 22 +- 15 files changed, 3023 insertions(+), 142 deletions(-) create mode 100644 .gitattributes create mode 100644 gen/host/installation/v1/installation.pb.go create mode 100644 gen/host/installation/v1/installationv1connect/installation.connect.go create mode 100644 gen/saas/accounts/v1/workload_operation_admission.pb.go diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dbb1f21 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +/gen/** linguist-generated=true diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a4dc98..1c763a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +### Added + +- Regenerate the host contract at `37b6003d`: source collection and placed-record + reads carry the viewer capability separately from the calling module proof. + Existing modules can use the authenticated module endpoint without presenting + a viewer as a module principal. Generation uses the existing pinned plugins. + Core main and module-saas-starter v0.0.103. No Core tag carries the Core this needs, so the floor is a pseudo-version; it moves to the first tag that does. diff --git a/README.md b/README.md index 7b46a94..6c816af 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ The SDK surfaces are: This call surface uses the four host RPCs from [module-saas-starter#1052](https://github.com/codefly-dev/module-saas-starter/pull/1052). - `SOURCE.txt` records the released host tag `v0.0.103` used to regenerate + `SOURCE.txt` records the exact host commit `37b6003d` used to regenerate the bindings. This regeneration does not publish an SDK release. The host's runtime-scheduled `PruneSourceOperationReceipts` and `LookupPruneSourceOperationReceipts` are included in the generated bindings @@ -507,11 +507,11 @@ proto ref `gen/` was generated from. ## Regenerating `gen/` The proto source of truth is `module-saas-starter/module/services/accounts/proto`. -To refresh from a released tag (in a checkout of that repo): +To reproduce the current development contract (in a checkout of that repo): ```bash -git fetch origin tag v0.0.103 -git checkout --detach v0.0.103 +git fetch origin 37b6003d4b21046916d53f8e94677a4b57beb2e3 +git checkout --detach 37b6003d4b21046916d53f8e94677a4b57beb2e3 cd module/services/accounts/proto buf generate --template /buf.gen.yaml -o ``` @@ -522,13 +522,13 @@ the correct module path. **Never hand-edit `gen/` or sed the module path** — t protobuf file descriptors embed length-prefixed package strings and a text rewrite corrupts them (panics at `init()`). Always regenerate. -The template generates the complete host-owned `saas/` schema tree. Its +The template generates the complete host-owned `saas/` schema tree and the +referenced host installation schema. Its vendored `codefly/` import closure is compiled for Runnable annotations, with imports resolved to `github.com/codefly-dev/core/generated/go`; Core owns those Go descriptors. Emitting a second copy in this SDK would conflict at protobuf initialization. The SDK requires Core at `b81d92e6feda` -(`v0.19.6-0.20261018051341-b81d92e6feda`), the Core the v0.0.103 gateway -requires: it supplies the Runnable package, and its `SealSource` has no +(`v0.19.6-0.20261018051341-b81d92e6feda`): it supplies the Runnable package, and its `SealSource` has no approved build. No tagged Core carries that yet; v0.19.5 still requires `SealSource.ApprovedBuild`, so it cannot build this SDK, and the floor moves to the first Core tag that contains `b81d92e6feda`. The SDK need not adopt the diff --git a/SOURCE.txt b/SOURCE.txt index 1e2661d..67cc1e2 100644 --- a/SOURCE.txt +++ b/SOURCE.txt @@ -1,11 +1,9 @@ -gen/ generated from codefly-dev/module-saas-starter@v0.0.103 +gen/ generated from codefly-dev/module-saas-starter@37b6003d4b21046916d53f8e94677a4b57beb2e3 (accounts public proto: module/services/accounts/proto) (auth gateway: module/services/auth-gateway/code) module version: 0.1.0 (module/module.package.codefly.yaml) This SDK's release is matched to the saas-starter module version above. -Released upstream tag: v0.0.103 (2cb00737ed56c79c823bc82f4055681a51919e7c). -Its auth gateway requires codefly-dev/core at b81d92e6feda, the floor this -SDK's go.mod records. +Exact upstream host selected for the hosted-eastus2 shared-authority deployment. Regeneration does not publish an SDK release. diff --git a/buf.gen.yaml b/buf.gen.yaml index 3663906..b74a8fe 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -2,10 +2,11 @@ version: v2 clean: true inputs: - directory: . - # Core's vendored import closure is compiled, but its Go bindings belong - # to the Core dependency. Generate every host-owned public schema. + # Core's vendored import closure stays with Core. Accounts now references + # host installation messages, so include that referenced schema too. paths: - saas + - host/installation/v1/installation.proto managed: enabled: true disable: diff --git a/gen/host/installation/v1/installation.pb.go b/gen/host/installation/v1/installation.pb.go new file mode 100644 index 0000000..63260d6 --- /dev/null +++ b/gen/host/installation/v1/installation.pb.go @@ -0,0 +1,1873 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: host/installation/v1/installation.proto + +// The installation interface: what is installed at an organisation and who may +// use it. An installed solution is a principal of its organisation; its roles +// are levels on the data that principal owns, and a grant of a role is the +// access. Operations on the host, and one the solution implements, the install +// step the host calls once per installation. + +package installationv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Status is the installation's lifecycle. +type Installation_Status int32 + +const ( + // Unset. + Installation_STATUS_UNSPECIFIED Installation_Status = 0 + // Installed; the install step has not been acknowledged. + Installation_STATUS_PENDING Installation_Status = 1 + // Usable. + Installation_STATUS_ACTIVE Installation_Status = 2 + // Uninstalled; every capability sealed to it is refused. + Installation_STATUS_REVOKED Installation_Status = 3 +) + +// Enum value maps for Installation_Status. +var ( + Installation_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "STATUS_PENDING", + 2: "STATUS_ACTIVE", + 3: "STATUS_REVOKED", + } + Installation_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 0, + "STATUS_PENDING": 1, + "STATUS_ACTIVE": 2, + "STATUS_REVOKED": 3, + } +) + +func (x Installation_Status) Enum() *Installation_Status { + p := new(Installation_Status) + *p = x + return p +} + +func (x Installation_Status) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Installation_Status) Descriptor() protoreflect.EnumDescriptor { + return file_host_installation_v1_installation_proto_enumTypes[0].Descriptor() +} + +func (Installation_Status) Type() protoreflect.EnumType { + return &file_host_installation_v1_installation_proto_enumTypes[0] +} + +func (x Installation_Status) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Installation_Status.Descriptor instead. +func (Installation_Status) EnumDescriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{12, 0} +} + +type CurrentInstallationRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ParentToken string `protobuf:"bytes,1,opt,name=parent_token,json=parentToken,proto3" json:"parent_token,omitempty"` + ActorCredential string `protobuf:"bytes,2,opt,name=actor_credential,json=actorCredential,proto3" json:"actor_credential,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CurrentInstallationRequest) Reset() { + *x = CurrentInstallationRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CurrentInstallationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CurrentInstallationRequest) ProtoMessage() {} + +func (x *CurrentInstallationRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CurrentInstallationRequest.ProtoReflect.Descriptor instead. +func (*CurrentInstallationRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{0} +} + +func (x *CurrentInstallationRequest) GetParentToken() string { + if x != nil { + return x.ParentToken + } + return "" +} + +func (x *CurrentInstallationRequest) GetActorCredential() string { + if x != nil { + return x.ActorCredential + } + return "" +} + +// CurrentInstallation is request-local metadata, never a lease or consent. +type CurrentInstallation struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + OrganizationId string `protobuf:"bytes,2,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + Target string `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` + Revision uint64 `protobuf:"varint,4,opt,name=revision,proto3" json:"revision,omitempty"` + Namespace string `protobuf:"bytes,5,opt,name=namespace,proto3" json:"namespace,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CurrentInstallation) Reset() { + *x = CurrentInstallation{} + mi := &file_host_installation_v1_installation_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CurrentInstallation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CurrentInstallation) ProtoMessage() {} + +func (x *CurrentInstallation) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CurrentInstallation.ProtoReflect.Descriptor instead. +func (*CurrentInstallation) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{1} +} + +func (x *CurrentInstallation) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *CurrentInstallation) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *CurrentInstallation) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *CurrentInstallation) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *CurrentInstallation) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +// InstallRequest asks to install one target at one organisation. +type InstallRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The organisation installing. + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + // The solution or module installed, by its name in the composition. + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + // The role the installation holds; the least privilege it needs. + Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"` + // The accountable person; an administrator of the organisation. + OwnerPersonId string `protobuf:"bytes,4,opt,name=owner_person_id,json=ownerPersonId,proto3" json:"owner_person_id,omitempty"` + // Required: the exact offer reviewed by the administrator; unchanged on retry. + Approval *ConsentApproval `protobuf:"bytes,5,opt,name=approval,proto3" json:"approval,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstallRequest) Reset() { + *x = InstallRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstallRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstallRequest) ProtoMessage() {} + +func (x *InstallRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InstallRequest.ProtoReflect.Descriptor instead. +func (*InstallRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{2} +} + +func (x *InstallRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *InstallRequest) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *InstallRequest) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *InstallRequest) GetOwnerPersonId() string { + if x != nil { + return x.OwnerPersonId + } + return "" +} + +func (x *InstallRequest) GetApproval() *ConsentApproval { + if x != nil { + return x.Approval + } + return nil +} + +// ReviewRequest names the offer an administrator intends to review. +type ReviewRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReviewRequest) Reset() { + *x = ReviewRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReviewRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReviewRequest) ProtoMessage() {} + +func (x *ReviewRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReviewRequest.ProtoReflect.Descriptor instead. +func (*ReviewRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{3} +} + +func (x *ReviewRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *ReviewRequest) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +// ConsentApproval binds consent to an immutable target, its reviewed delivery and +// the installation revision (zero if absent). Review leaves operation_id empty; +// the caller supplies a fresh UUID and preserves the entire request on retry. +type ConsentApproval struct { + state protoimpl.MessageState `protogen:"open.v1"` + TargetId string `protobuf:"bytes,1,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` + Generation uint64 `protobuf:"varint,2,opt,name=generation,proto3" json:"generation,omitempty"` + ExpectedRevision uint64 `protobuf:"varint,3,opt,name=expected_revision,json=expectedRevision,proto3" json:"expected_revision,omitempty"` + OperationId string `protobuf:"bytes,4,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + // sha256 digest of the reviewed authority offer. + Digest string `protobuf:"bytes,5,opt,name=digest,proto3" json:"digest,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConsentApproval) Reset() { + *x = ConsentApproval{} + mi := &file_host_installation_v1_installation_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsentApproval) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsentApproval) ProtoMessage() {} + +func (x *ConsentApproval) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConsentApproval.ProtoReflect.Descriptor instead. +func (*ConsentApproval) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{4} +} + +func (x *ConsentApproval) GetTargetId() string { + if x != nil { + return x.TargetId + } + return "" +} + +func (x *ConsentApproval) GetGeneration() uint64 { + if x != nil { + return x.Generation + } + return 0 +} + +func (x *ConsentApproval) GetExpectedRevision() uint64 { + if x != nil { + return x.ExpectedRevision + } + return 0 +} + +func (x *ConsentApproval) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +func (x *ConsentApproval) GetDigest() string { + if x != nil { + return x.Digest + } + return "" +} + +// GrantRoleRequest grants one role to exactly one person or team. +type GrantRoleRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The organization the installation belongs to; a request naming another + // organization's installation is refused naming the organization, before + // the caller's authority is read. + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + // The installation. + InstallationId string `protobuf:"bytes,2,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"` + // One of the roles the solution declares. + Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"` + // The person granted, a member of the organization; exactly one of + // person_id and team_id is set. + PersonId string `protobuf:"bytes,4,opt,name=person_id,json=personId,proto3" json:"person_id,omitempty"` + // The team granted, a team of the organization. + TeamId string `protobuf:"bytes,5,opt,name=team_id,json=teamId,proto3" json:"team_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GrantRoleRequest) Reset() { + *x = GrantRoleRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GrantRoleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GrantRoleRequest) ProtoMessage() {} + +func (x *GrantRoleRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GrantRoleRequest.ProtoReflect.Descriptor instead. +func (*GrantRoleRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{5} +} + +func (x *GrantRoleRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *GrantRoleRequest) GetInstallationId() string { + if x != nil { + return x.InstallationId + } + return "" +} + +func (x *GrantRoleRequest) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *GrantRoleRequest) GetPersonId() string { + if x != nil { + return x.PersonId + } + return "" +} + +func (x *GrantRoleRequest) GetTeamId() string { + if x != nil { + return x.TeamId + } + return "" +} + +// RevokeRoleRequest ends one grant, named as GrantRole named it. +type RevokeRoleRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The organization the installation belongs to. + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + // The installation. + InstallationId string `protobuf:"bytes,2,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"` + // The role. + Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"` + // The person; exactly one of person_id and team_id is set. + PersonId string `protobuf:"bytes,4,opt,name=person_id,json=personId,proto3" json:"person_id,omitempty"` + // The team. + TeamId string `protobuf:"bytes,5,opt,name=team_id,json=teamId,proto3" json:"team_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RevokeRoleRequest) Reset() { + *x = RevokeRoleRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RevokeRoleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RevokeRoleRequest) ProtoMessage() {} + +func (x *RevokeRoleRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RevokeRoleRequest.ProtoReflect.Descriptor instead. +func (*RevokeRoleRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{6} +} + +func (x *RevokeRoleRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *RevokeRoleRequest) GetInstallationId() string { + if x != nil { + return x.InstallationId + } + return "" +} + +func (x *RevokeRoleRequest) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *RevokeRoleRequest) GetPersonId() string { + if x != nil { + return x.PersonId + } + return "" +} + +func (x *RevokeRoleRequest) GetTeamId() string { + if x != nil { + return x.TeamId + } + return "" +} + +// ListRoleGrantsRequest names one installation. +type ListRoleGrantsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The organization the installation belongs to. + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + // The installation. + InstallationId string `protobuf:"bytes,2,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRoleGrantsRequest) Reset() { + *x = ListRoleGrantsRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRoleGrantsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRoleGrantsRequest) ProtoMessage() {} + +func (x *ListRoleGrantsRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRoleGrantsRequest.ProtoReflect.Descriptor instead. +func (*ListRoleGrantsRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{7} +} + +func (x *ListRoleGrantsRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *ListRoleGrantsRequest) GetInstallationId() string { + if x != nil { + return x.InstallationId + } + return "" +} + +// ListRoleGrantsResponse is every grant on the installation. +type ListRoleGrantsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The grants. + Grants []*RoleGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRoleGrantsResponse) Reset() { + *x = ListRoleGrantsResponse{} + mi := &file_host_installation_v1_installation_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRoleGrantsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRoleGrantsResponse) ProtoMessage() {} + +func (x *ListRoleGrantsResponse) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRoleGrantsResponse.ProtoReflect.Descriptor instead. +func (*ListRoleGrantsResponse) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{8} +} + +func (x *ListRoleGrantsResponse) GetGrants() []*RoleGrant { + if x != nil { + return x.Grants + } + return nil +} + +// RoleGrant is one role held by one person or team. +type RoleGrant struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The role. + Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` + // The person, when a person holds it. + PersonId string `protobuf:"bytes,2,opt,name=person_id,json=personId,proto3" json:"person_id,omitempty"` + // The team, when a team holds it. + TeamId string `protobuf:"bytes,3,opt,name=team_id,json=teamId,proto3" json:"team_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleGrant) Reset() { + *x = RoleGrant{} + mi := &file_host_installation_v1_installation_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleGrant) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleGrant) ProtoMessage() {} + +func (x *RoleGrant) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RoleGrant.ProtoReflect.Descriptor instead. +func (*RoleGrant) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{9} +} + +func (x *RoleGrant) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *RoleGrant) GetPersonId() string { + if x != nil { + return x.PersonId + } + return "" +} + +func (x *RoleGrant) GetTeamId() string { + if x != nil { + return x.TeamId + } + return "" +} + +// ListRequest asks for one organisation's installations. +type ListRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The organisation. + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRequest) Reset() { + *x = ListRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest) ProtoMessage() {} + +func (x *ListRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead. +func (*ListRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{10} +} + +func (x *ListRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +// ListResponse lists installations. +type ListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The installations. + Installations []*Installation `protobuf:"bytes,1,rep,name=installations,proto3" json:"installations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListResponse) Reset() { + *x = ListResponse{} + mi := &file_host_installation_v1_installation_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse) ProtoMessage() {} + +func (x *ListResponse) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead. +func (*ListResponse) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{11} +} + +func (x *ListResponse) GetInstallations() []*Installation { + if x != nil { + return x.Installations + } + return nil +} + +// Installation is one organisation's installation of one target. +type Installation struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The installation id. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The organisation. + OrganizationId string `protobuf:"bytes,2,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + // The target installed. + Target string `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` + // Where the installation stands. + Status Installation_Status `protobuf:"varint,4,opt,name=status,proto3,enum=host.installation.v1.Installation_Status" json:"status,omitempty"` + // Bumped on every change that narrows or widens the installation. + Revision uint64 `protobuf:"varint,5,opt,name=revision,proto3" json:"revision,omitempty"` + // The role the installation holds when it acts for itself (its agent's + // role); no person or team inherits it. + Role string `protobuf:"bytes,6,opt,name=role,proto3" json:"role,omitempty"` + // The namespace the installation's own authored content belongs to (an + // agent's source): the host names it, so a module never chooses which source + // an installation may run. A module installed by composition is + // ".". + Namespace string `protobuf:"bytes,9,opt,name=namespace,proto3" json:"namespace,omitempty"` + // The solution principal: the identity the installation's data is owned by + // and the installation acts as for itself, a stable UUID per organization + // and target, reused by a reinstall. Empty for a module installation. + PrincipalId string `protobuf:"bytes,10,opt,name=principal_id,json=principalId,proto3" json:"principal_id,omitempty"` + // The roles the solution declares, sorted. + Roles []string `protobuf:"bytes,11,rep,name=roles,proto3" json:"roles,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Installation) Reset() { + *x = Installation{} + mi := &file_host_installation_v1_installation_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Installation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Installation) ProtoMessage() {} + +func (x *Installation) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Installation.ProtoReflect.Descriptor instead. +func (*Installation) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{12} +} + +func (x *Installation) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Installation) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +func (x *Installation) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *Installation) GetStatus() Installation_Status { + if x != nil { + return x.Status + } + return Installation_STATUS_UNSPECIFIED +} + +func (x *Installation) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *Installation) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *Installation) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Installation) GetPrincipalId() string { + if x != nil { + return x.PrincipalId + } + return "" +} + +func (x *Installation) GetRoles() []string { + if x != nil { + return x.Roles + } + return nil +} + +// InstallationNotice is what the host hands the solution's install step. +type InstallationNotice struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The installation being set up. + Installation *Installation `protobuf:"bytes,1,opt,name=installation,proto3" json:"installation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstallationNotice) Reset() { + *x = InstallationNotice{} + mi := &file_host_installation_v1_installation_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstallationNotice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstallationNotice) ProtoMessage() {} + +func (x *InstallationNotice) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InstallationNotice.ProtoReflect.Descriptor instead. +func (*InstallationNotice) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{13} +} + +func (x *InstallationNotice) GetInstallation() *Installation { + if x != nil { + return x.Installation + } + return nil +} + +// InstallationAck acknowledges the install step. +type InstallationAck struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InstallationAck) Reset() { + *x = InstallationAck{} + mi := &file_host_installation_v1_installation_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InstallationAck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InstallationAck) ProtoMessage() {} + +func (x *InstallationAck) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InstallationAck.ProtoReflect.Descriptor instead. +func (*InstallationAck) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{14} +} + +// ListOffersRequest names the organization whose administrator reads. +type ListOffersRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrganizationId string `protobuf:"bytes,1,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListOffersRequest) Reset() { + *x = ListOffersRequest{} + mi := &file_host_installation_v1_installation_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListOffersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListOffersRequest) ProtoMessage() {} + +func (x *ListOffersRequest) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListOffersRequest.ProtoReflect.Descriptor instead. +func (*ListOffersRequest) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{15} +} + +func (x *ListOffersRequest) GetOrganizationId() string { + if x != nil { + return x.OrganizationId + } + return "" +} + +// ListOffersResponse is every delivered solution, by name. +type ListOffersResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Offers []*Offer `protobuf:"bytes,1,rep,name=offers,proto3" json:"offers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListOffersResponse) Reset() { + *x = ListOffersResponse{} + mi := &file_host_installation_v1_installation_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListOffersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListOffersResponse) ProtoMessage() {} + +func (x *ListOffersResponse) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListOffersResponse.ProtoReflect.Descriptor instead. +func (*ListOffersResponse) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{16} +} + +func (x *ListOffersResponse) GetOffers() []*Offer { + if x != nil { + return x.Offers + } + return nil +} + +// Offer is one delivered solution. +type Offer struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The solution's name in the composition: Install's target. + Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` + // The delivery generation an approval binds. + Generation uint64 `protobuf:"varint,2,opt,name=generation,proto3" json:"generation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Offer) Reset() { + *x = Offer{} + mi := &file_host_installation_v1_installation_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Offer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Offer) ProtoMessage() {} + +func (x *Offer) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Offer.ProtoReflect.Descriptor instead. +func (*Offer) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{17} +} + +func (x *Offer) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *Offer) GetGeneration() uint64 { + if x != nil { + return x.Generation + } + return 0 +} + +// ReviewedOffer is one solution's authority offer and the consent that names it. +type ReviewedOffer struct { + state protoimpl.MessageState `protogen:"open.v1"` + // What Install takes, with a fresh operation_id; read with the rest. + Approval *ConsentApproval `protobuf:"bytes,1,opt,name=approval,proto3" json:"approval,omitempty"` + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + // Each role the solution declares, the installer role included. Every role + // scope is confined to this installation: to what it owns, or to the + // resources attached to it. + Roles []*OfferRole `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty"` + // The solution's own installation at the organization; absent before Install. + Installation *Installation `protobuf:"bytes,4,opt,name=installation,proto3" json:"installation,omitempty"` + // The permission ceiling: each module the solution calls, and the most it + // may ask there. No role reaches beyond it. + Ceiling []*OfferBinding `protobuf:"bytes,5,rep,name=ceiling,proto3" json:"ceiling,omitempty"` + // False when this run delivered no prepared Runnable bindings: no tool is + // shown, which says nothing about what a composed binding would expose. + ToolsComposed bool `protobuf:"varint,6,opt,name=tools_composed,json=toolsComposed,proto3" json:"tools_composed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReviewedOffer) Reset() { + *x = ReviewedOffer{} + mi := &file_host_installation_v1_installation_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReviewedOffer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReviewedOffer) ProtoMessage() {} + +func (x *ReviewedOffer) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReviewedOffer.ProtoReflect.Descriptor instead. +func (*ReviewedOffer) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{18} +} + +func (x *ReviewedOffer) GetApproval() *ConsentApproval { + if x != nil { + return x.Approval + } + return nil +} + +func (x *ReviewedOffer) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *ReviewedOffer) GetRoles() []*OfferRole { + if x != nil { + return x.Roles + } + return nil +} + +func (x *ReviewedOffer) GetInstallation() *Installation { + if x != nil { + return x.Installation + } + return nil +} + +func (x *ReviewedOffer) GetCeiling() []*OfferBinding { + if x != nil { + return x.Ceiling + } + return nil +} + +func (x *ReviewedOffer) GetToolsComposed() bool { + if x != nil { + return x.ToolsComposed + } + return false +} + +// OfferBinding is one declared call from the solution to a module. +type OfferBinding struct { + state protoimpl.MessageState `protogen:"open.v1"` + Binding string `protobuf:"bytes,1,opt,name=binding,proto3" json:"binding,omitempty"` + // The module called. + Module string `protobuf:"bytes,2,opt,name=module,proto3" json:"module,omitempty"` + Scopes []*OfferScope `protobuf:"bytes,3,rep,name=scopes,proto3" json:"scopes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OfferBinding) Reset() { + *x = OfferBinding{} + mi := &file_host_installation_v1_installation_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OfferBinding) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OfferBinding) ProtoMessage() {} + +func (x *OfferBinding) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OfferBinding.ProtoReflect.Descriptor instead. +func (*OfferBinding) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{19} +} + +func (x *OfferBinding) GetBinding() string { + if x != nil { + return x.Binding + } + return "" +} + +func (x *OfferBinding) GetModule() string { + if x != nil { + return x.Module + } + return "" +} + +func (x *OfferBinding) GetScopes() []*OfferScope { + if x != nil { + return x.Scopes + } + return nil +} + +// OfferRole is one declared role and what a grant of it reaches. +type OfferRole struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The scopes the role declares. + Scopes []*OfferScope `protobuf:"bytes,2,rep,name=scopes,proto3" json:"scopes,omitempty"` + // Each composed operation the role's scopes cover. + Capabilities []*OfferCapability `protobuf:"bytes,3,rep,name=capabilities,proto3" json:"capabilities,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OfferRole) Reset() { + *x = OfferRole{} + mi := &file_host_installation_v1_installation_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OfferRole) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OfferRole) ProtoMessage() {} + +func (x *OfferRole) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OfferRole.ProtoReflect.Descriptor instead. +func (*OfferRole) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{20} +} + +func (x *OfferRole) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *OfferRole) GetScopes() []*OfferScope { + if x != nil { + return x.Scopes + } + return nil +} + +func (x *OfferRole) GetCapabilities() []*OfferCapability { + if x != nil { + return x.Capabilities + } + return nil +} + +// OfferScope is one declared scope. +type OfferScope struct { + state protoimpl.MessageState `protogen:"open.v1"` + ResourceKind string `protobuf:"bytes,1,opt,name=resource_kind,json=resourceKind,proto3" json:"resource_kind,omitempty"` + Actions []string `protobuf:"bytes,2,rep,name=actions,proto3" json:"actions,omitempty"` + // True when the scope reaches only the resources attached to the + // installation, listed in resource_ids (none until one is attached); false + // when it reaches every resource the installation owns. + AttachedOnly bool `protobuf:"varint,3,opt,name=attached_only,json=attachedOnly,proto3" json:"attached_only,omitempty"` + ResourceIds []string `protobuf:"bytes,4,rep,name=resource_ids,json=resourceIds,proto3" json:"resource_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OfferScope) Reset() { + *x = OfferScope{} + mi := &file_host_installation_v1_installation_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OfferScope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OfferScope) ProtoMessage() {} + +func (x *OfferScope) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OfferScope.ProtoReflect.Descriptor instead. +func (*OfferScope) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{21} +} + +func (x *OfferScope) GetResourceKind() string { + if x != nil { + return x.ResourceKind + } + return "" +} + +func (x *OfferScope) GetActions() []string { + if x != nil { + return x.Actions + } + return nil +} + +func (x *OfferScope) GetAttachedOnly() bool { + if x != nil { + return x.AttachedOnly + } + return false +} + +func (x *OfferScope) GetResourceIds() []string { + if x != nil { + return x.ResourceIds + } + return nil +} + +// OfferCapability is one module operation a role's scopes cover. +type OfferCapability struct { + state protoimpl.MessageState `protogen:"open.v1"` + Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"` + // The operation as the module's authority document names it. + Operation string `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"` + // What a call to it must hold. + Requires []*OfferScope `protobuf:"bytes,3,rep,name=requires,proto3" json:"requires,omitempty"` + // The tools composed for this operation, from its prepared Runnable + // bindings; empty when no binding exposes it as a tool. + Tools []*OfferTool `protobuf:"bytes,4,rep,name=tools,proto3" json:"tools,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OfferCapability) Reset() { + *x = OfferCapability{} + mi := &file_host_installation_v1_installation_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OfferCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OfferCapability) ProtoMessage() {} + +func (x *OfferCapability) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OfferCapability.ProtoReflect.Descriptor instead. +func (*OfferCapability) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{22} +} + +func (x *OfferCapability) GetModule() string { + if x != nil { + return x.Module + } + return "" +} + +func (x *OfferCapability) GetOperation() string { + if x != nil { + return x.Operation + } + return "" +} + +func (x *OfferCapability) GetRequires() []*OfferScope { + if x != nil { + return x.Requires + } + return nil +} + +func (x *OfferCapability) GetTools() []*OfferTool { + if x != nil { + return x.Tools + } + return nil +} + +// OfferTool is one tool-exposed Runnable of an operation. +type OfferTool struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The tool's name, as its exposure declares it. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The prepared binding a caller names to run it. + Binding string `protobuf:"bytes,2,opt,name=binding,proto3" json:"binding,omitempty"` + // True when the tool changes data. + Write bool `protobuf:"varint,3,opt,name=write,proto3" json:"write,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OfferTool) Reset() { + *x = OfferTool{} + mi := &file_host_installation_v1_installation_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OfferTool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OfferTool) ProtoMessage() {} + +func (x *OfferTool) ProtoReflect() protoreflect.Message { + mi := &file_host_installation_v1_installation_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OfferTool.ProtoReflect.Descriptor instead. +func (*OfferTool) Descriptor() ([]byte, []int) { + return file_host_installation_v1_installation_proto_rawDescGZIP(), []int{23} +} + +func (x *OfferTool) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *OfferTool) GetBinding() string { + if x != nil { + return x.Binding + } + return "" +} + +func (x *OfferTool) GetWrite() bool { + if x != nil { + return x.Write + } + return false +} + +var File_host_installation_v1_installation_proto protoreflect.FileDescriptor + +const file_host_installation_v1_installation_proto_rawDesc = "" + + "\n" + + "'host/installation/v1/installation.proto\x12\x14host.installation.v1\"j\n" + + "\x1aCurrentInstallationRequest\x12!\n" + + "\fparent_token\x18\x01 \x01(\tR\vparentToken\x12)\n" + + "\x10actor_credential\x18\x02 \x01(\tR\x0factorCredential\"\xa0\x01\n" + + "\x13CurrentInstallation\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12'\n" + + "\x0forganization_id\x18\x02 \x01(\tR\x0eorganizationId\x12\x16\n" + + "\x06target\x18\x03 \x01(\tR\x06target\x12\x1a\n" + + "\brevision\x18\x04 \x01(\x04R\brevision\x12\x1c\n" + + "\tnamespace\x18\x05 \x01(\tR\tnamespace\"\xd0\x01\n" + + "\x0eInstallRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12\x16\n" + + "\x06target\x18\x02 \x01(\tR\x06target\x12\x12\n" + + "\x04role\x18\x03 \x01(\tR\x04role\x12&\n" + + "\x0fowner_person_id\x18\x04 \x01(\tR\rownerPersonId\x12A\n" + + "\bapproval\x18\x05 \x01(\v2%.host.installation.v1.ConsentApprovalR\bapproval\"P\n" + + "\rReviewRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12\x16\n" + + "\x06target\x18\x02 \x01(\tR\x06target\"\xb6\x01\n" + + "\x0fConsentApproval\x12\x1b\n" + + "\ttarget_id\x18\x01 \x01(\tR\btargetId\x12\x1e\n" + + "\n" + + "generation\x18\x02 \x01(\x04R\n" + + "generation\x12+\n" + + "\x11expected_revision\x18\x03 \x01(\x04R\x10expectedRevision\x12!\n" + + "\foperation_id\x18\x04 \x01(\tR\voperationId\x12\x16\n" + + "\x06digest\x18\x05 \x01(\tR\x06digest\"\xae\x01\n" + + "\x10GrantRoleRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12'\n" + + "\x0finstallation_id\x18\x02 \x01(\tR\x0einstallationId\x12\x12\n" + + "\x04role\x18\x03 \x01(\tR\x04role\x12\x1b\n" + + "\tperson_id\x18\x04 \x01(\tR\bpersonId\x12\x17\n" + + "\ateam_id\x18\x05 \x01(\tR\x06teamId\"\xaf\x01\n" + + "\x11RevokeRoleRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12'\n" + + "\x0finstallation_id\x18\x02 \x01(\tR\x0einstallationId\x12\x12\n" + + "\x04role\x18\x03 \x01(\tR\x04role\x12\x1b\n" + + "\tperson_id\x18\x04 \x01(\tR\bpersonId\x12\x17\n" + + "\ateam_id\x18\x05 \x01(\tR\x06teamId\"i\n" + + "\x15ListRoleGrantsRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12'\n" + + "\x0finstallation_id\x18\x02 \x01(\tR\x0einstallationId\"Q\n" + + "\x16ListRoleGrantsResponse\x127\n" + + "\x06grants\x18\x01 \x03(\v2\x1f.host.installation.v1.RoleGrantR\x06grants\"U\n" + + "\tRoleGrant\x12\x12\n" + + "\x04role\x18\x01 \x01(\tR\x04role\x12\x1b\n" + + "\tperson_id\x18\x02 \x01(\tR\bpersonId\x12\x17\n" + + "\ateam_id\x18\x03 \x01(\tR\x06teamId\"6\n" + + "\vListRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\"X\n" + + "\fListResponse\x12H\n" + + "\rinstallations\x18\x01 \x03(\v2\".host.installation.v1.InstallationR\rinstallations\"\xb0\x03\n" + + "\fInstallation\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12'\n" + + "\x0forganization_id\x18\x02 \x01(\tR\x0eorganizationId\x12\x16\n" + + "\x06target\x18\x03 \x01(\tR\x06target\x12A\n" + + "\x06status\x18\x04 \x01(\x0e2).host.installation.v1.Installation.StatusR\x06status\x12\x1a\n" + + "\brevision\x18\x05 \x01(\x04R\brevision\x12\x12\n" + + "\x04role\x18\x06 \x01(\tR\x04role\x12\x1c\n" + + "\tnamespace\x18\t \x01(\tR\tnamespace\x12!\n" + + "\fprincipal_id\x18\n" + + " \x01(\tR\vprincipalId\x12\x14\n" + + "\x05roles\x18\v \x03(\tR\x05roles\"[\n" + + "\x06Status\x12\x16\n" + + "\x12STATUS_UNSPECIFIED\x10\x00\x12\x12\n" + + "\x0eSTATUS_PENDING\x10\x01\x12\x11\n" + + "\rSTATUS_ACTIVE\x10\x02\x12\x12\n" + + "\x0eSTATUS_REVOKED\x10\x03J\x04\b\a\x10\bJ\x04\b\b\x10\tR\bteam_idsR\x12agent_principal_id\"\\\n" + + "\x12InstallationNotice\x12F\n" + + "\finstallation\x18\x01 \x01(\v2\".host.installation.v1.InstallationR\finstallation\"\x11\n" + + "\x0fInstallationAck\"<\n" + + "\x11ListOffersRequest\x12'\n" + + "\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\"I\n" + + "\x12ListOffersResponse\x123\n" + + "\x06offers\x18\x01 \x03(\v2\x1b.host.installation.v1.OfferR\x06offers\"?\n" + + "\x05Offer\x12\x16\n" + + "\x06target\x18\x01 \x01(\tR\x06target\x12\x1e\n" + + "\n" + + "generation\x18\x02 \x01(\x04R\n" + + "generation\"\xce\x02\n" + + "\rReviewedOffer\x12A\n" + + "\bapproval\x18\x01 \x01(\v2%.host.installation.v1.ConsentApprovalR\bapproval\x12\x16\n" + + "\x06target\x18\x02 \x01(\tR\x06target\x125\n" + + "\x05roles\x18\x03 \x03(\v2\x1f.host.installation.v1.OfferRoleR\x05roles\x12F\n" + + "\finstallation\x18\x04 \x01(\v2\".host.installation.v1.InstallationR\finstallation\x12<\n" + + "\aceiling\x18\x05 \x03(\v2\".host.installation.v1.OfferBindingR\aceiling\x12%\n" + + "\x0etools_composed\x18\x06 \x01(\bR\rtoolsComposed\"z\n" + + "\fOfferBinding\x12\x18\n" + + "\abinding\x18\x01 \x01(\tR\abinding\x12\x16\n" + + "\x06module\x18\x02 \x01(\tR\x06module\x128\n" + + "\x06scopes\x18\x03 \x03(\v2 .host.installation.v1.OfferScopeR\x06scopes\"\xa4\x01\n" + + "\tOfferRole\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x128\n" + + "\x06scopes\x18\x02 \x03(\v2 .host.installation.v1.OfferScopeR\x06scopes\x12I\n" + + "\fcapabilities\x18\x03 \x03(\v2%.host.installation.v1.OfferCapabilityR\fcapabilities\"\x93\x01\n" + + "\n" + + "OfferScope\x12#\n" + + "\rresource_kind\x18\x01 \x01(\tR\fresourceKind\x12\x18\n" + + "\aactions\x18\x02 \x03(\tR\aactions\x12#\n" + + "\rattached_only\x18\x03 \x01(\bR\fattachedOnly\x12!\n" + + "\fresource_ids\x18\x04 \x03(\tR\vresourceIds\"\xbc\x01\n" + + "\x0fOfferCapability\x12\x16\n" + + "\x06module\x18\x01 \x01(\tR\x06module\x12\x1c\n" + + "\toperation\x18\x02 \x01(\tR\toperation\x12<\n" + + "\brequires\x18\x03 \x03(\v2 .host.installation.v1.OfferScopeR\brequires\x125\n" + + "\x05tools\x18\x04 \x03(\v2\x1f.host.installation.v1.OfferToolR\x05tools\"O\n" + + "\tOfferTool\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" + + "\abinding\x18\x02 \x01(\tR\abinding\x12\x14\n" + + "\x05write\x18\x03 \x01(\bR\x05write2\x98\x05\n" + + "\x13InstallationService\x12f\n" + + "\aCurrent\x120.host.installation.v1.CurrentInstallationRequest\x1a).host.installation.v1.CurrentInstallation\x12S\n" + + "\aInstall\x12$.host.installation.v1.InstallRequest\x1a\".host.installation.v1.Installation\x12T\n" + + "\x06Review\x12#.host.installation.v1.ReviewRequest\x1a%.host.installation.v1.ConsentApproval\x12W\n" + + "\tGrantRole\x12&.host.installation.v1.GrantRoleRequest\x1a\".host.installation.v1.Installation\x12Y\n" + + "\n" + + "RevokeRole\x12'.host.installation.v1.RevokeRoleRequest\x1a\".host.installation.v1.Installation\x12k\n" + + "\x0eListRoleGrants\x12+.host.installation.v1.ListRoleGrantsRequest\x1a,.host.installation.v1.ListRoleGrantsResponse\x12M\n" + + "\x04List\x12!.host.installation.v1.ListRequest\x1a\".host.installation.v1.ListResponse2p\n" + + "\x12InstallableService\x12Z\n" + + "\aInstall\x12(.host.installation.v1.InstallationNotice\x1a%.host.installation.v1.InstallationAck2\xc8\x01\n" + + "\fOfferService\x12_\n" + + "\n" + + "ListOffers\x12'.host.installation.v1.ListOffersRequest\x1a(.host.installation.v1.ListOffersResponse\x12W\n" + + "\vReviewOffer\x12#.host.installation.v1.ReviewRequest\x1a#.host.installation.v1.ReviewedOfferB\xeb\x01\n" + + "\x18com.host.installation.v1B\x11InstallationProtoP\x01ZJgithub.com/codefly-dev/saas-sdk-go/gen/host/installation/v1;installationv1\xa2\x02\x03HIX\xaa\x02\x14Host.Installation.V1\xca\x02\x14Host\\Installation\\V1\xe2\x02 Host\\Installation\\V1\\GPBMetadata\xea\x02\x16Host::Installation::V1b\x06proto3" + +var ( + file_host_installation_v1_installation_proto_rawDescOnce sync.Once + file_host_installation_v1_installation_proto_rawDescData []byte +) + +func file_host_installation_v1_installation_proto_rawDescGZIP() []byte { + file_host_installation_v1_installation_proto_rawDescOnce.Do(func() { + file_host_installation_v1_installation_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_host_installation_v1_installation_proto_rawDesc), len(file_host_installation_v1_installation_proto_rawDesc))) + }) + return file_host_installation_v1_installation_proto_rawDescData +} + +var file_host_installation_v1_installation_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_host_installation_v1_installation_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_host_installation_v1_installation_proto_goTypes = []any{ + (Installation_Status)(0), // 0: host.installation.v1.Installation.Status + (*CurrentInstallationRequest)(nil), // 1: host.installation.v1.CurrentInstallationRequest + (*CurrentInstallation)(nil), // 2: host.installation.v1.CurrentInstallation + (*InstallRequest)(nil), // 3: host.installation.v1.InstallRequest + (*ReviewRequest)(nil), // 4: host.installation.v1.ReviewRequest + (*ConsentApproval)(nil), // 5: host.installation.v1.ConsentApproval + (*GrantRoleRequest)(nil), // 6: host.installation.v1.GrantRoleRequest + (*RevokeRoleRequest)(nil), // 7: host.installation.v1.RevokeRoleRequest + (*ListRoleGrantsRequest)(nil), // 8: host.installation.v1.ListRoleGrantsRequest + (*ListRoleGrantsResponse)(nil), // 9: host.installation.v1.ListRoleGrantsResponse + (*RoleGrant)(nil), // 10: host.installation.v1.RoleGrant + (*ListRequest)(nil), // 11: host.installation.v1.ListRequest + (*ListResponse)(nil), // 12: host.installation.v1.ListResponse + (*Installation)(nil), // 13: host.installation.v1.Installation + (*InstallationNotice)(nil), // 14: host.installation.v1.InstallationNotice + (*InstallationAck)(nil), // 15: host.installation.v1.InstallationAck + (*ListOffersRequest)(nil), // 16: host.installation.v1.ListOffersRequest + (*ListOffersResponse)(nil), // 17: host.installation.v1.ListOffersResponse + (*Offer)(nil), // 18: host.installation.v1.Offer + (*ReviewedOffer)(nil), // 19: host.installation.v1.ReviewedOffer + (*OfferBinding)(nil), // 20: host.installation.v1.OfferBinding + (*OfferRole)(nil), // 21: host.installation.v1.OfferRole + (*OfferScope)(nil), // 22: host.installation.v1.OfferScope + (*OfferCapability)(nil), // 23: host.installation.v1.OfferCapability + (*OfferTool)(nil), // 24: host.installation.v1.OfferTool +} +var file_host_installation_v1_installation_proto_depIdxs = []int32{ + 5, // 0: host.installation.v1.InstallRequest.approval:type_name -> host.installation.v1.ConsentApproval + 10, // 1: host.installation.v1.ListRoleGrantsResponse.grants:type_name -> host.installation.v1.RoleGrant + 13, // 2: host.installation.v1.ListResponse.installations:type_name -> host.installation.v1.Installation + 0, // 3: host.installation.v1.Installation.status:type_name -> host.installation.v1.Installation.Status + 13, // 4: host.installation.v1.InstallationNotice.installation:type_name -> host.installation.v1.Installation + 18, // 5: host.installation.v1.ListOffersResponse.offers:type_name -> host.installation.v1.Offer + 5, // 6: host.installation.v1.ReviewedOffer.approval:type_name -> host.installation.v1.ConsentApproval + 21, // 7: host.installation.v1.ReviewedOffer.roles:type_name -> host.installation.v1.OfferRole + 13, // 8: host.installation.v1.ReviewedOffer.installation:type_name -> host.installation.v1.Installation + 20, // 9: host.installation.v1.ReviewedOffer.ceiling:type_name -> host.installation.v1.OfferBinding + 22, // 10: host.installation.v1.OfferBinding.scopes:type_name -> host.installation.v1.OfferScope + 22, // 11: host.installation.v1.OfferRole.scopes:type_name -> host.installation.v1.OfferScope + 23, // 12: host.installation.v1.OfferRole.capabilities:type_name -> host.installation.v1.OfferCapability + 22, // 13: host.installation.v1.OfferCapability.requires:type_name -> host.installation.v1.OfferScope + 24, // 14: host.installation.v1.OfferCapability.tools:type_name -> host.installation.v1.OfferTool + 1, // 15: host.installation.v1.InstallationService.Current:input_type -> host.installation.v1.CurrentInstallationRequest + 3, // 16: host.installation.v1.InstallationService.Install:input_type -> host.installation.v1.InstallRequest + 4, // 17: host.installation.v1.InstallationService.Review:input_type -> host.installation.v1.ReviewRequest + 6, // 18: host.installation.v1.InstallationService.GrantRole:input_type -> host.installation.v1.GrantRoleRequest + 7, // 19: host.installation.v1.InstallationService.RevokeRole:input_type -> host.installation.v1.RevokeRoleRequest + 8, // 20: host.installation.v1.InstallationService.ListRoleGrants:input_type -> host.installation.v1.ListRoleGrantsRequest + 11, // 21: host.installation.v1.InstallationService.List:input_type -> host.installation.v1.ListRequest + 14, // 22: host.installation.v1.InstallableService.Install:input_type -> host.installation.v1.InstallationNotice + 16, // 23: host.installation.v1.OfferService.ListOffers:input_type -> host.installation.v1.ListOffersRequest + 4, // 24: host.installation.v1.OfferService.ReviewOffer:input_type -> host.installation.v1.ReviewRequest + 2, // 25: host.installation.v1.InstallationService.Current:output_type -> host.installation.v1.CurrentInstallation + 13, // 26: host.installation.v1.InstallationService.Install:output_type -> host.installation.v1.Installation + 5, // 27: host.installation.v1.InstallationService.Review:output_type -> host.installation.v1.ConsentApproval + 13, // 28: host.installation.v1.InstallationService.GrantRole:output_type -> host.installation.v1.Installation + 13, // 29: host.installation.v1.InstallationService.RevokeRole:output_type -> host.installation.v1.Installation + 9, // 30: host.installation.v1.InstallationService.ListRoleGrants:output_type -> host.installation.v1.ListRoleGrantsResponse + 12, // 31: host.installation.v1.InstallationService.List:output_type -> host.installation.v1.ListResponse + 15, // 32: host.installation.v1.InstallableService.Install:output_type -> host.installation.v1.InstallationAck + 17, // 33: host.installation.v1.OfferService.ListOffers:output_type -> host.installation.v1.ListOffersResponse + 19, // 34: host.installation.v1.OfferService.ReviewOffer:output_type -> host.installation.v1.ReviewedOffer + 25, // [25:35] is the sub-list for method output_type + 15, // [15:25] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name +} + +func init() { file_host_installation_v1_installation_proto_init() } +func file_host_installation_v1_installation_proto_init() { + if File_host_installation_v1_installation_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_host_installation_v1_installation_proto_rawDesc), len(file_host_installation_v1_installation_proto_rawDesc)), + NumEnums: 1, + NumMessages: 24, + NumExtensions: 0, + NumServices: 3, + }, + GoTypes: file_host_installation_v1_installation_proto_goTypes, + DependencyIndexes: file_host_installation_v1_installation_proto_depIdxs, + EnumInfos: file_host_installation_v1_installation_proto_enumTypes, + MessageInfos: file_host_installation_v1_installation_proto_msgTypes, + }.Build() + File_host_installation_v1_installation_proto = out.File + file_host_installation_v1_installation_proto_goTypes = nil + file_host_installation_v1_installation_proto_depIdxs = nil +} diff --git a/gen/host/installation/v1/installationv1connect/installation.connect.go b/gen/host/installation/v1/installationv1connect/installation.connect.go new file mode 100644 index 0000000..990338a --- /dev/null +++ b/gen/host/installation/v1/installationv1connect/installation.connect.go @@ -0,0 +1,516 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: host/installation/v1/installation.proto + +// The installation interface: what is installed at an organisation and who may +// use it. An installed solution is a principal of its organisation; its roles +// are levels on the data that principal owns, and a grant of a role is the +// access. Operations on the host, and one the solution implements, the install +// step the host calls once per installation. +package installationv1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/codefly-dev/saas-sdk-go/gen/host/installation/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // InstallationServiceName is the fully-qualified name of the InstallationService service. + InstallationServiceName = "host.installation.v1.InstallationService" + // InstallableServiceName is the fully-qualified name of the InstallableService service. + InstallableServiceName = "host.installation.v1.InstallableService" + // OfferServiceName is the fully-qualified name of the OfferService service. + OfferServiceName = "host.installation.v1.OfferService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // InstallationServiceCurrentProcedure is the fully-qualified name of the InstallationService's + // Current RPC. + InstallationServiceCurrentProcedure = "/host.installation.v1.InstallationService/Current" + // InstallationServiceInstallProcedure is the fully-qualified name of the InstallationService's + // Install RPC. + InstallationServiceInstallProcedure = "/host.installation.v1.InstallationService/Install" + // InstallationServiceReviewProcedure is the fully-qualified name of the InstallationService's + // Review RPC. + InstallationServiceReviewProcedure = "/host.installation.v1.InstallationService/Review" + // InstallationServiceGrantRoleProcedure is the fully-qualified name of the InstallationService's + // GrantRole RPC. + InstallationServiceGrantRoleProcedure = "/host.installation.v1.InstallationService/GrantRole" + // InstallationServiceRevokeRoleProcedure is the fully-qualified name of the InstallationService's + // RevokeRole RPC. + InstallationServiceRevokeRoleProcedure = "/host.installation.v1.InstallationService/RevokeRole" + // InstallationServiceListRoleGrantsProcedure is the fully-qualified name of the + // InstallationService's ListRoleGrants RPC. + InstallationServiceListRoleGrantsProcedure = "/host.installation.v1.InstallationService/ListRoleGrants" + // InstallationServiceListProcedure is the fully-qualified name of the InstallationService's List + // RPC. + InstallationServiceListProcedure = "/host.installation.v1.InstallationService/List" + // InstallableServiceInstallProcedure is the fully-qualified name of the InstallableService's + // Install RPC. + InstallableServiceInstallProcedure = "/host.installation.v1.InstallableService/Install" + // OfferServiceListOffersProcedure is the fully-qualified name of the OfferService's ListOffers RPC. + OfferServiceListOffersProcedure = "/host.installation.v1.OfferService/ListOffers" + // OfferServiceReviewOfferProcedure is the fully-qualified name of the OfferService's ReviewOffer + // RPC. + OfferServiceReviewOfferProcedure = "/host.installation.v1.OfferService/ReviewOffer" +) + +// InstallationServiceClient is a client for the host.installation.v1.InstallationService service. +type InstallationServiceClient interface { + // Current reads only the authenticated module's own active installation, + // in the tenant of a current parent addressed to that module. It grants no + // artifact approval or content access and exposes no roles or grants. + Current(context.Context, *connect.Request[v1.CurrentInstallationRequest]) (*connect.Response[v1.CurrentInstallation], error) + // Install composes an installation: its agent principal, its root scope and + // the row, pending until the target acknowledges its install step. + Install(context.Context, *connect.Request[v1.InstallRequest]) (*connect.Response[v1.Installation], error) + // Review reads the current offer and installation revision without granting consent. + Review(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ConsentApproval], error) + // GrantRole grants a person or a team one of the solution's roles on the + // installation: the access. Idempotent; it leaves existing capabilities + // valid. An administrator of the installation's organization, or a holder + // of the installer role on that installation, grants. + GrantRole(context.Context, *connect.Request[v1.GrantRoleRequest]) (*connect.Response[v1.Installation], error) + // RevokeRole ends one grant; every capability its subject holds from it is + // refused at once. Idempotent; the same callers as GrantRole. + RevokeRole(context.Context, *connect.Request[v1.RevokeRoleRequest]) (*connect.Response[v1.Installation], error) + // ListRoleGrants answers who holds which role on the installation; the same + // callers as GrantRole. + ListRoleGrants(context.Context, *connect.Request[v1.ListRoleGrantsRequest]) (*connect.Response[v1.ListRoleGrantsResponse], error) + // List answers what one organisation has installed: an administrator's read. A + // member's view, which installed solutions they may use, is their navigation and + // belongs to the entitlement read, not here. + List(context.Context, *connect.Request[v1.ListRequest]) (*connect.Response[v1.ListResponse], error) +} + +// NewInstallationServiceClient constructs a client for the host.installation.v1.InstallationService +// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for +// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply +// the connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewInstallationServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) InstallationServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + installationServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("InstallationService").Methods() + return &installationServiceClient{ + current: connect.NewClient[v1.CurrentInstallationRequest, v1.CurrentInstallation]( + httpClient, + baseURL+InstallationServiceCurrentProcedure, + connect.WithSchema(installationServiceMethods.ByName("Current")), + connect.WithClientOptions(opts...), + ), + install: connect.NewClient[v1.InstallRequest, v1.Installation]( + httpClient, + baseURL+InstallationServiceInstallProcedure, + connect.WithSchema(installationServiceMethods.ByName("Install")), + connect.WithClientOptions(opts...), + ), + review: connect.NewClient[v1.ReviewRequest, v1.ConsentApproval]( + httpClient, + baseURL+InstallationServiceReviewProcedure, + connect.WithSchema(installationServiceMethods.ByName("Review")), + connect.WithClientOptions(opts...), + ), + grantRole: connect.NewClient[v1.GrantRoleRequest, v1.Installation]( + httpClient, + baseURL+InstallationServiceGrantRoleProcedure, + connect.WithSchema(installationServiceMethods.ByName("GrantRole")), + connect.WithClientOptions(opts...), + ), + revokeRole: connect.NewClient[v1.RevokeRoleRequest, v1.Installation]( + httpClient, + baseURL+InstallationServiceRevokeRoleProcedure, + connect.WithSchema(installationServiceMethods.ByName("RevokeRole")), + connect.WithClientOptions(opts...), + ), + listRoleGrants: connect.NewClient[v1.ListRoleGrantsRequest, v1.ListRoleGrantsResponse]( + httpClient, + baseURL+InstallationServiceListRoleGrantsProcedure, + connect.WithSchema(installationServiceMethods.ByName("ListRoleGrants")), + connect.WithClientOptions(opts...), + ), + list: connect.NewClient[v1.ListRequest, v1.ListResponse]( + httpClient, + baseURL+InstallationServiceListProcedure, + connect.WithSchema(installationServiceMethods.ByName("List")), + connect.WithClientOptions(opts...), + ), + } +} + +// installationServiceClient implements InstallationServiceClient. +type installationServiceClient struct { + current *connect.Client[v1.CurrentInstallationRequest, v1.CurrentInstallation] + install *connect.Client[v1.InstallRequest, v1.Installation] + review *connect.Client[v1.ReviewRequest, v1.ConsentApproval] + grantRole *connect.Client[v1.GrantRoleRequest, v1.Installation] + revokeRole *connect.Client[v1.RevokeRoleRequest, v1.Installation] + listRoleGrants *connect.Client[v1.ListRoleGrantsRequest, v1.ListRoleGrantsResponse] + list *connect.Client[v1.ListRequest, v1.ListResponse] +} + +// Current calls host.installation.v1.InstallationService.Current. +func (c *installationServiceClient) Current(ctx context.Context, req *connect.Request[v1.CurrentInstallationRequest]) (*connect.Response[v1.CurrentInstallation], error) { + return c.current.CallUnary(ctx, req) +} + +// Install calls host.installation.v1.InstallationService.Install. +func (c *installationServiceClient) Install(ctx context.Context, req *connect.Request[v1.InstallRequest]) (*connect.Response[v1.Installation], error) { + return c.install.CallUnary(ctx, req) +} + +// Review calls host.installation.v1.InstallationService.Review. +func (c *installationServiceClient) Review(ctx context.Context, req *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ConsentApproval], error) { + return c.review.CallUnary(ctx, req) +} + +// GrantRole calls host.installation.v1.InstallationService.GrantRole. +func (c *installationServiceClient) GrantRole(ctx context.Context, req *connect.Request[v1.GrantRoleRequest]) (*connect.Response[v1.Installation], error) { + return c.grantRole.CallUnary(ctx, req) +} + +// RevokeRole calls host.installation.v1.InstallationService.RevokeRole. +func (c *installationServiceClient) RevokeRole(ctx context.Context, req *connect.Request[v1.RevokeRoleRequest]) (*connect.Response[v1.Installation], error) { + return c.revokeRole.CallUnary(ctx, req) +} + +// ListRoleGrants calls host.installation.v1.InstallationService.ListRoleGrants. +func (c *installationServiceClient) ListRoleGrants(ctx context.Context, req *connect.Request[v1.ListRoleGrantsRequest]) (*connect.Response[v1.ListRoleGrantsResponse], error) { + return c.listRoleGrants.CallUnary(ctx, req) +} + +// List calls host.installation.v1.InstallationService.List. +func (c *installationServiceClient) List(ctx context.Context, req *connect.Request[v1.ListRequest]) (*connect.Response[v1.ListResponse], error) { + return c.list.CallUnary(ctx, req) +} + +// InstallationServiceHandler is an implementation of the host.installation.v1.InstallationService +// service. +type InstallationServiceHandler interface { + // Current reads only the authenticated module's own active installation, + // in the tenant of a current parent addressed to that module. It grants no + // artifact approval or content access and exposes no roles or grants. + Current(context.Context, *connect.Request[v1.CurrentInstallationRequest]) (*connect.Response[v1.CurrentInstallation], error) + // Install composes an installation: its agent principal, its root scope and + // the row, pending until the target acknowledges its install step. + Install(context.Context, *connect.Request[v1.InstallRequest]) (*connect.Response[v1.Installation], error) + // Review reads the current offer and installation revision without granting consent. + Review(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ConsentApproval], error) + // GrantRole grants a person or a team one of the solution's roles on the + // installation: the access. Idempotent; it leaves existing capabilities + // valid. An administrator of the installation's organization, or a holder + // of the installer role on that installation, grants. + GrantRole(context.Context, *connect.Request[v1.GrantRoleRequest]) (*connect.Response[v1.Installation], error) + // RevokeRole ends one grant; every capability its subject holds from it is + // refused at once. Idempotent; the same callers as GrantRole. + RevokeRole(context.Context, *connect.Request[v1.RevokeRoleRequest]) (*connect.Response[v1.Installation], error) + // ListRoleGrants answers who holds which role on the installation; the same + // callers as GrantRole. + ListRoleGrants(context.Context, *connect.Request[v1.ListRoleGrantsRequest]) (*connect.Response[v1.ListRoleGrantsResponse], error) + // List answers what one organisation has installed: an administrator's read. A + // member's view, which installed solutions they may use, is their navigation and + // belongs to the entitlement read, not here. + List(context.Context, *connect.Request[v1.ListRequest]) (*connect.Response[v1.ListResponse], error) +} + +// NewInstallationServiceHandler builds an HTTP handler from the service implementation. It returns +// the path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewInstallationServiceHandler(svc InstallationServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + installationServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("InstallationService").Methods() + installationServiceCurrentHandler := connect.NewUnaryHandler( + InstallationServiceCurrentProcedure, + svc.Current, + connect.WithSchema(installationServiceMethods.ByName("Current")), + connect.WithHandlerOptions(opts...), + ) + installationServiceInstallHandler := connect.NewUnaryHandler( + InstallationServiceInstallProcedure, + svc.Install, + connect.WithSchema(installationServiceMethods.ByName("Install")), + connect.WithHandlerOptions(opts...), + ) + installationServiceReviewHandler := connect.NewUnaryHandler( + InstallationServiceReviewProcedure, + svc.Review, + connect.WithSchema(installationServiceMethods.ByName("Review")), + connect.WithHandlerOptions(opts...), + ) + installationServiceGrantRoleHandler := connect.NewUnaryHandler( + InstallationServiceGrantRoleProcedure, + svc.GrantRole, + connect.WithSchema(installationServiceMethods.ByName("GrantRole")), + connect.WithHandlerOptions(opts...), + ) + installationServiceRevokeRoleHandler := connect.NewUnaryHandler( + InstallationServiceRevokeRoleProcedure, + svc.RevokeRole, + connect.WithSchema(installationServiceMethods.ByName("RevokeRole")), + connect.WithHandlerOptions(opts...), + ) + installationServiceListRoleGrantsHandler := connect.NewUnaryHandler( + InstallationServiceListRoleGrantsProcedure, + svc.ListRoleGrants, + connect.WithSchema(installationServiceMethods.ByName("ListRoleGrants")), + connect.WithHandlerOptions(opts...), + ) + installationServiceListHandler := connect.NewUnaryHandler( + InstallationServiceListProcedure, + svc.List, + connect.WithSchema(installationServiceMethods.ByName("List")), + connect.WithHandlerOptions(opts...), + ) + return "/host.installation.v1.InstallationService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case InstallationServiceCurrentProcedure: + installationServiceCurrentHandler.ServeHTTP(w, r) + case InstallationServiceInstallProcedure: + installationServiceInstallHandler.ServeHTTP(w, r) + case InstallationServiceReviewProcedure: + installationServiceReviewHandler.ServeHTTP(w, r) + case InstallationServiceGrantRoleProcedure: + installationServiceGrantRoleHandler.ServeHTTP(w, r) + case InstallationServiceRevokeRoleProcedure: + installationServiceRevokeRoleHandler.ServeHTTP(w, r) + case InstallationServiceListRoleGrantsProcedure: + installationServiceListRoleGrantsHandler.ServeHTTP(w, r) + case InstallationServiceListProcedure: + installationServiceListHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedInstallationServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedInstallationServiceHandler struct{} + +func (UnimplementedInstallationServiceHandler) Current(context.Context, *connect.Request[v1.CurrentInstallationRequest]) (*connect.Response[v1.CurrentInstallation], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.Current is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) Install(context.Context, *connect.Request[v1.InstallRequest]) (*connect.Response[v1.Installation], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.Install is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) Review(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ConsentApproval], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.Review is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) GrantRole(context.Context, *connect.Request[v1.GrantRoleRequest]) (*connect.Response[v1.Installation], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.GrantRole is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) RevokeRole(context.Context, *connect.Request[v1.RevokeRoleRequest]) (*connect.Response[v1.Installation], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.RevokeRole is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) ListRoleGrants(context.Context, *connect.Request[v1.ListRoleGrantsRequest]) (*connect.Response[v1.ListRoleGrantsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.ListRoleGrants is not implemented")) +} + +func (UnimplementedInstallationServiceHandler) List(context.Context, *connect.Request[v1.ListRequest]) (*connect.Response[v1.ListResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallationService.List is not implemented")) +} + +// InstallableServiceClient is a client for the host.installation.v1.InstallableService service. +type InstallableServiceClient interface { + // Install sets up the solution for one installation; it must converge. + Install(context.Context, *connect.Request[v1.InstallationNotice]) (*connect.Response[v1.InstallationAck], error) +} + +// NewInstallableServiceClient constructs a client for the host.installation.v1.InstallableService +// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for +// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply +// the connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewInstallableServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) InstallableServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + installableServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("InstallableService").Methods() + return &installableServiceClient{ + install: connect.NewClient[v1.InstallationNotice, v1.InstallationAck]( + httpClient, + baseURL+InstallableServiceInstallProcedure, + connect.WithSchema(installableServiceMethods.ByName("Install")), + connect.WithClientOptions(opts...), + ), + } +} + +// installableServiceClient implements InstallableServiceClient. +type installableServiceClient struct { + install *connect.Client[v1.InstallationNotice, v1.InstallationAck] +} + +// Install calls host.installation.v1.InstallableService.Install. +func (c *installableServiceClient) Install(ctx context.Context, req *connect.Request[v1.InstallationNotice]) (*connect.Response[v1.InstallationAck], error) { + return c.install.CallUnary(ctx, req) +} + +// InstallableServiceHandler is an implementation of the host.installation.v1.InstallableService +// service. +type InstallableServiceHandler interface { + // Install sets up the solution for one installation; it must converge. + Install(context.Context, *connect.Request[v1.InstallationNotice]) (*connect.Response[v1.InstallationAck], error) +} + +// NewInstallableServiceHandler builds an HTTP handler from the service implementation. It returns +// the path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewInstallableServiceHandler(svc InstallableServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + installableServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("InstallableService").Methods() + installableServiceInstallHandler := connect.NewUnaryHandler( + InstallableServiceInstallProcedure, + svc.Install, + connect.WithSchema(installableServiceMethods.ByName("Install")), + connect.WithHandlerOptions(opts...), + ) + return "/host.installation.v1.InstallableService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case InstallableServiceInstallProcedure: + installableServiceInstallHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedInstallableServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedInstallableServiceHandler struct{} + +func (UnimplementedInstallableServiceHandler) Install(context.Context, *connect.Request[v1.InstallationNotice]) (*connect.Response[v1.InstallationAck], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.InstallableService.Install is not implemented")) +} + +// OfferServiceClient is a client for the host.installation.v1.OfferService service. +type OfferServiceClient interface { + // ListOffers lists the solutions delivered to this run that an administrator + // of the organization may install. A module is installed by composition and + // is never offered. + ListOffers(context.Context, *connect.Request[v1.ListOffersRequest]) (*connect.Response[v1.ListOffersResponse], error) + // ReviewOffer reads one solution's roles, what each grants and the tools + // those grants make eligible, with the consent Install takes, from one read + // of the authority: the approval names exactly the offer displayed. + ReviewOffer(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ReviewedOffer], error) +} + +// NewOfferServiceClient constructs a client for the host.installation.v1.OfferService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewOfferServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) OfferServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + offerServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("OfferService").Methods() + return &offerServiceClient{ + listOffers: connect.NewClient[v1.ListOffersRequest, v1.ListOffersResponse]( + httpClient, + baseURL+OfferServiceListOffersProcedure, + connect.WithSchema(offerServiceMethods.ByName("ListOffers")), + connect.WithClientOptions(opts...), + ), + reviewOffer: connect.NewClient[v1.ReviewRequest, v1.ReviewedOffer]( + httpClient, + baseURL+OfferServiceReviewOfferProcedure, + connect.WithSchema(offerServiceMethods.ByName("ReviewOffer")), + connect.WithClientOptions(opts...), + ), + } +} + +// offerServiceClient implements OfferServiceClient. +type offerServiceClient struct { + listOffers *connect.Client[v1.ListOffersRequest, v1.ListOffersResponse] + reviewOffer *connect.Client[v1.ReviewRequest, v1.ReviewedOffer] +} + +// ListOffers calls host.installation.v1.OfferService.ListOffers. +func (c *offerServiceClient) ListOffers(ctx context.Context, req *connect.Request[v1.ListOffersRequest]) (*connect.Response[v1.ListOffersResponse], error) { + return c.listOffers.CallUnary(ctx, req) +} + +// ReviewOffer calls host.installation.v1.OfferService.ReviewOffer. +func (c *offerServiceClient) ReviewOffer(ctx context.Context, req *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ReviewedOffer], error) { + return c.reviewOffer.CallUnary(ctx, req) +} + +// OfferServiceHandler is an implementation of the host.installation.v1.OfferService service. +type OfferServiceHandler interface { + // ListOffers lists the solutions delivered to this run that an administrator + // of the organization may install. A module is installed by composition and + // is never offered. + ListOffers(context.Context, *connect.Request[v1.ListOffersRequest]) (*connect.Response[v1.ListOffersResponse], error) + // ReviewOffer reads one solution's roles, what each grants and the tools + // those grants make eligible, with the consent Install takes, from one read + // of the authority: the approval names exactly the offer displayed. + ReviewOffer(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ReviewedOffer], error) +} + +// NewOfferServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewOfferServiceHandler(svc OfferServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + offerServiceMethods := v1.File_host_installation_v1_installation_proto.Services().ByName("OfferService").Methods() + offerServiceListOffersHandler := connect.NewUnaryHandler( + OfferServiceListOffersProcedure, + svc.ListOffers, + connect.WithSchema(offerServiceMethods.ByName("ListOffers")), + connect.WithHandlerOptions(opts...), + ) + offerServiceReviewOfferHandler := connect.NewUnaryHandler( + OfferServiceReviewOfferProcedure, + svc.ReviewOffer, + connect.WithSchema(offerServiceMethods.ByName("ReviewOffer")), + connect.WithHandlerOptions(opts...), + ) + return "/host.installation.v1.OfferService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case OfferServiceListOffersProcedure: + offerServiceListOffersHandler.ServeHTTP(w, r) + case OfferServiceReviewOfferProcedure: + offerServiceReviewOfferHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedOfferServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedOfferServiceHandler struct{} + +func (UnimplementedOfferServiceHandler) ListOffers(context.Context, *connect.Request[v1.ListOffersRequest]) (*connect.Response[v1.ListOffersResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.OfferService.ListOffers is not implemented")) +} + +func (UnimplementedOfferServiceHandler) ReviewOffer(context.Context, *connect.Request[v1.ReviewRequest]) (*connect.Response[v1.ReviewedOffer], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("host.installation.v1.OfferService.ReviewOffer is not implemented")) +} diff --git a/gen/saas/accounts/v1/accountsv1connect/installations.connect.go b/gen/saas/accounts/v1/accountsv1connect/installations.connect.go index 57ca8be..40d1e5d 100644 --- a/gen/saas/accounts/v1/accountsv1connect/installations.connect.go +++ b/gen/saas/accounts/v1/accountsv1connect/installations.connect.go @@ -81,8 +81,8 @@ type InstallationServiceClient interface { // is left in place (inert without a grant or a live agent) so a reinstall reuses // it. Idempotent on an already-revoked installation. UninstallSolution(context.Context, *connect.Request[v1.UninstallSolutionRequest]) (*connect.Response[emptypb.Empty], error) - // Narrowing is witnessed in the policy log before commit, then atomically - // bumps the installation revision, cancels its org's work and records audit. + // A narrowing applies directly: it atomically bumps the installation + // revision, cancels its org's work and records audit. NarrowInstallation(context.Context, *connect.Request[v1.NarrowInstallationRequest]) (*connect.Response[emptypb.Empty], error) // RetryInstallation runs a failed installation's install step again, at the // same revision. The installation is pending until the solution acknowledges. @@ -149,9 +149,8 @@ type InstallationServiceClient interface { // ListOrganizationInstallations describes. GrantInstallationToTeam(context.Context, *connect.Request[v1.GrantInstallationToTeamRequest]) (*connect.Response[v1.GrantInstallationToTeamResponse], error) // RevokeInstallationFromTeam removes one team grant at an installation's - // authority-root node. It is a narrowing, so it runs under the policy log - // exactly as RevokeScope does: a host that cannot witness the narrowing refuses - // it, and says so, rather than revoking unwitnessed. It removes the one grant + // authority-root node. It is a narrowing, so it applies directly, with its + // audit record in one transaction, exactly as RevokeScope does. It removes the one grant // at the authority root that granted_teams reports; a team that also reaches // the installation from a grant above keeps that reach. Organisation-admin, // with the same platform super administrator exception. @@ -323,8 +322,8 @@ type InstallationServiceHandler interface { // is left in place (inert without a grant or a live agent) so a reinstall reuses // it. Idempotent on an already-revoked installation. UninstallSolution(context.Context, *connect.Request[v1.UninstallSolutionRequest]) (*connect.Response[emptypb.Empty], error) - // Narrowing is witnessed in the policy log before commit, then atomically - // bumps the installation revision, cancels its org's work and records audit. + // A narrowing applies directly: it atomically bumps the installation + // revision, cancels its org's work and records audit. NarrowInstallation(context.Context, *connect.Request[v1.NarrowInstallationRequest]) (*connect.Response[emptypb.Empty], error) // RetryInstallation runs a failed installation's install step again, at the // same revision. The installation is pending until the solution acknowledges. @@ -391,9 +390,8 @@ type InstallationServiceHandler interface { // ListOrganizationInstallations describes. GrantInstallationToTeam(context.Context, *connect.Request[v1.GrantInstallationToTeamRequest]) (*connect.Response[v1.GrantInstallationToTeamResponse], error) // RevokeInstallationFromTeam removes one team grant at an installation's - // authority-root node. It is a narrowing, so it runs under the policy log - // exactly as RevokeScope does: a host that cannot witness the narrowing refuses - // it, and says so, rather than revoking unwitnessed. It removes the one grant + // authority-root node. It is a narrowing, so it applies directly, with its + // audit record in one transaction, exactly as RevokeScope does. It removes the one grant // at the authority root that granted_teams reports; a team that also reaches // the installation from a grant above keeps that reach. Organisation-admin, // with the same platform super administrator exception. diff --git a/gen/saas/accounts/v1/accountsv1connect/work_contexts.connect.go b/gen/saas/accounts/v1/accountsv1connect/work_contexts.connect.go index b1cb716..6130c60 100644 --- a/gen/saas/accounts/v1/accountsv1connect/work_contexts.connect.go +++ b/gen/saas/accounts/v1/accountsv1connect/work_contexts.connect.go @@ -43,6 +43,9 @@ const ( // WorkContextServiceConsumeSingleUseProcedure is the fully-qualified name of the // WorkContextService's ConsumeSingleUse RPC. WorkContextServiceConsumeSingleUseProcedure = "/saas.accounts.v1.WorkContextService/ConsumeSingleUse" + // WorkContextServiceAdmitWorkloadOperationProcedure is the fully-qualified name of the + // WorkContextService's AdmitWorkloadOperation RPC. + WorkContextServiceAdmitWorkloadOperationProcedure = "/saas.accounts.v1.WorkContextService/AdmitWorkloadOperation" // WorkContextServiceStartTaskProcedure is the fully-qualified name of the WorkContextService's // StartTask RPC. WorkContextServiceStartTaskProcedure = "/saas.accounts.v1.WorkContextService/StartTask" @@ -82,6 +85,19 @@ type WorkContextServiceClient interface { // a replay and returns ALREADY_EXISTS. A caller must treat that as the // capability being spent and fail the operation closed, not retry it. ConsumeSingleUse(context.Context, *connect.Request[v1.ConsumeSingleUseWorkContextRequest]) (*connect.Response[emptypb.Empty], error) + // AdmitWorkloadOperation answers whether a capability presented with no + // bearer at the declared module route /v1//* is a module operation + // context (StartModuleOperationTask) for that alias, and admits nothing else; + // and whether the route's target is installed in the capability's tenant. + // The auth-gateway's bearer-less arm is its caller. Unlike the revision + // checks above, the signed capability itself crosses this boundary: the + // answer depends on its owner, owner kind and chain, which only the issuer + // reads. It reads the capability back (core's Authority.ReadBack: signature + // under this issuer, window, audience, revision, seal, epochs) and never + // verifies it as presented, so nothing is consumed and the callee still + // verifies at full strength. Internal-tier: the tenant it answers about is + // the one the capability names. + AdmitWorkloadOperation(context.Context, *connect.Request[v1.AdmitWorkloadOperationRequest]) (*connect.Response[v1.AdmitWorkloadOperationResponse], error) StartTask(context.Context, *connect.Request[v1.StartTaskWorkContextRequest]) (*connect.Response[v1.IssuedWorkContext], error) // StartInstallationTask is the headless mint. Unlike StartTask it opens with a // service credential rather than a bearer: it resolves the installation's owner @@ -135,6 +151,12 @@ func NewWorkContextServiceClient(httpClient connect.HTTPClient, baseURL string, connect.WithSchema(workContextServiceMethods.ByName("ConsumeSingleUse")), connect.WithClientOptions(opts...), ), + admitWorkloadOperation: connect.NewClient[v1.AdmitWorkloadOperationRequest, v1.AdmitWorkloadOperationResponse]( + httpClient, + baseURL+WorkContextServiceAdmitWorkloadOperationProcedure, + connect.WithSchema(workContextServiceMethods.ByName("AdmitWorkloadOperation")), + connect.WithClientOptions(opts...), + ), startTask: connect.NewClient[v1.StartTaskWorkContextRequest, v1.IssuedWorkContext]( httpClient, baseURL+WorkContextServiceStartTaskProcedure, @@ -179,6 +201,7 @@ type workContextServiceClient struct { checkAuthorizationRevision *connect.Client[v1.CheckAuthorizationRevisionRequest, emptypb.Empty] authorizeEvidenceRead *connect.Client[v1.AuthorizeEvidenceReadRequest, emptypb.Empty] consumeSingleUse *connect.Client[v1.ConsumeSingleUseWorkContextRequest, emptypb.Empty] + admitWorkloadOperation *connect.Client[v1.AdmitWorkloadOperationRequest, v1.AdmitWorkloadOperationResponse] startTask *connect.Client[v1.StartTaskWorkContextRequest, v1.IssuedWorkContext] startInstallationTask *connect.Client[v1.StartInstallationTaskRequest, v1.IssuedWorkContext] startRootSession *connect.Client[v1.StartRootSessionWorkContextRequest, v1.IssuedWorkContext] @@ -202,6 +225,11 @@ func (c *workContextServiceClient) ConsumeSingleUse(ctx context.Context, req *co return c.consumeSingleUse.CallUnary(ctx, req) } +// AdmitWorkloadOperation calls saas.accounts.v1.WorkContextService.AdmitWorkloadOperation. +func (c *workContextServiceClient) AdmitWorkloadOperation(ctx context.Context, req *connect.Request[v1.AdmitWorkloadOperationRequest]) (*connect.Response[v1.AdmitWorkloadOperationResponse], error) { + return c.admitWorkloadOperation.CallUnary(ctx, req) +} + // StartTask calls saas.accounts.v1.WorkContextService.StartTask. func (c *workContextServiceClient) StartTask(ctx context.Context, req *connect.Request[v1.StartTaskWorkContextRequest]) (*connect.Response[v1.IssuedWorkContext], error) { return c.startTask.CallUnary(ctx, req) @@ -252,6 +280,19 @@ type WorkContextServiceHandler interface { // a replay and returns ALREADY_EXISTS. A caller must treat that as the // capability being spent and fail the operation closed, not retry it. ConsumeSingleUse(context.Context, *connect.Request[v1.ConsumeSingleUseWorkContextRequest]) (*connect.Response[emptypb.Empty], error) + // AdmitWorkloadOperation answers whether a capability presented with no + // bearer at the declared module route /v1//* is a module operation + // context (StartModuleOperationTask) for that alias, and admits nothing else; + // and whether the route's target is installed in the capability's tenant. + // The auth-gateway's bearer-less arm is its caller. Unlike the revision + // checks above, the signed capability itself crosses this boundary: the + // answer depends on its owner, owner kind and chain, which only the issuer + // reads. It reads the capability back (core's Authority.ReadBack: signature + // under this issuer, window, audience, revision, seal, epochs) and never + // verifies it as presented, so nothing is consumed and the callee still + // verifies at full strength. Internal-tier: the tenant it answers about is + // the one the capability names. + AdmitWorkloadOperation(context.Context, *connect.Request[v1.AdmitWorkloadOperationRequest]) (*connect.Response[v1.AdmitWorkloadOperationResponse], error) StartTask(context.Context, *connect.Request[v1.StartTaskWorkContextRequest]) (*connect.Response[v1.IssuedWorkContext], error) // StartInstallationTask is the headless mint. Unlike StartTask it opens with a // service credential rather than a bearer: it resolves the installation's owner @@ -301,6 +342,12 @@ func NewWorkContextServiceHandler(svc WorkContextServiceHandler, opts ...connect connect.WithSchema(workContextServiceMethods.ByName("ConsumeSingleUse")), connect.WithHandlerOptions(opts...), ) + workContextServiceAdmitWorkloadOperationHandler := connect.NewUnaryHandler( + WorkContextServiceAdmitWorkloadOperationProcedure, + svc.AdmitWorkloadOperation, + connect.WithSchema(workContextServiceMethods.ByName("AdmitWorkloadOperation")), + connect.WithHandlerOptions(opts...), + ) workContextServiceStartTaskHandler := connect.NewUnaryHandler( WorkContextServiceStartTaskProcedure, svc.StartTask, @@ -345,6 +392,8 @@ func NewWorkContextServiceHandler(svc WorkContextServiceHandler, opts ...connect workContextServiceAuthorizeEvidenceReadHandler.ServeHTTP(w, r) case WorkContextServiceConsumeSingleUseProcedure: workContextServiceConsumeSingleUseHandler.ServeHTTP(w, r) + case WorkContextServiceAdmitWorkloadOperationProcedure: + workContextServiceAdmitWorkloadOperationHandler.ServeHTTP(w, r) case WorkContextServiceStartTaskProcedure: workContextServiceStartTaskHandler.ServeHTTP(w, r) case WorkContextServiceStartInstallationTaskProcedure: @@ -378,6 +427,10 @@ func (UnimplementedWorkContextServiceHandler) ConsumeSingleUse(context.Context, return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.WorkContextService.ConsumeSingleUse is not implemented")) } +func (UnimplementedWorkContextServiceHandler) AdmitWorkloadOperation(context.Context, *connect.Request[v1.AdmitWorkloadOperationRequest]) (*connect.Response[v1.AdmitWorkloadOperationResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.WorkContextService.AdmitWorkloadOperation is not implemented")) +} + func (UnimplementedWorkContextServiceHandler) StartTask(context.Context, *connect.Request[v1.StartTaskWorkContextRequest]) (*connect.Response[v1.IssuedWorkContext], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("saas.accounts.v1.WorkContextService.StartTask is not implemented")) } diff --git a/gen/saas/accounts/v1/datasource.pb.go b/gen/saas/accounts/v1/datasource.pb.go index ba4782c..9633707 100644 --- a/gen/saas/accounts/v1/datasource.pb.go +++ b/gen/saas/accounts/v1/datasource.pb.go @@ -7017,14 +7017,18 @@ func (x *ListSourceOperationsResponse) GetOperations() []*SourceOperation { // InvokeSourceOperationRequest carries exactly one JSON object in input_json. // effect_id must match x-codefly-effect-id; either location may supply it. type InvokeSourceOperationRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` - SourceId string `protobuf:"bytes,2,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` - Operation string `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` - InputJson string `protobuf:"bytes,4,opt,name=input_json,json=inputJson,proto3" json:"input_json,omitempty"` - EffectId string `protobuf:"bytes,5,opt,name=effect_id,json=effectId,proto3" json:"effect_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + SourceId string `protobuf:"bytes,2,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` + Operation string `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` + InputJson string `protobuf:"bytes,4,opt,name=input_json,json=inputJson,proto3" json:"input_json,omitempty"` + EffectId string `protobuf:"bytes,5,opt,name=effect_id,json=effectId,proto3" json:"effect_id,omitempty"` + // Optional for legacy callers. A caller that admitted a declaration supplies + // its canonical digest; a replacement is refused before provider dispatch. + // This precondition participates in the receipt request fingerprint. + ExpectedDeclarationDigest *string `protobuf:"bytes,6,opt,name=expected_declaration_digest,json=expectedDeclarationDigest,proto3,oneof" json:"expected_declaration_digest,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *InvokeSourceOperationRequest) Reset() { @@ -7092,6 +7096,13 @@ func (x *InvokeSourceOperationRequest) GetEffectId() string { return "" } +func (x *InvokeSourceOperationRequest) GetExpectedDeclarationDigest() string { + if x != nil && x.ExpectedDeclarationDigest != nil { + return *x.ExpectedDeclarationDigest + } + return "" +} + // SourceOperationReceipt contains only the committed result and safe metadata. type SourceOperationReceipt struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -7919,14 +7930,16 @@ const file_saas_accounts_v1_datasource_proto_rawDesc = "" + "\x1cListSourceOperationsResponse\x12A\n" + "\n" + "operations\x18\x01 \x03(\v2!.saas.accounts.v1.SourceOperationR\n" + - "operations\"\xf4\x01\n" + + "operations\"\xfa\x02\n" + "\x1cInvokeSourceOperationRequest\x12\x1f\n" + "\x06org_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x05orgId\x12%\n" + "\tsource_id\x18\x02 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\bsourceId\x12;\n" + "\toperation\x18\x03 \x01(\tB\x1d\xbaH\x1ar\x182\x16^[a-z][a-z0-9_]{0,63}$R\toperation\x12(\n" + "\n" + "input_json\x18\x04 \x01(\tB\t\xbaH\x06r\x04(\x80\x80\x04R\tinputJson\x12%\n" + - "\teffect_id\x18\x05 \x01(\tB\b\xbaH\x05r\x03(\x80\x01R\beffectId\"\xba\x01\n" + + "\teffect_id\x18\x05 \x01(\tB\b\xbaH\x05r\x03(\x80\x01R\beffectId\x12d\n" + + "\x1bexpected_declaration_digest\x18\x06 \x01(\tB\x1f\xbaH\x1cr\x1a2\x18^(sha256:[0-9a-f]{64})?$H\x00R\x19expectedDeclarationDigest\x88\x01\x01B\x1e\n" + + "\x1c_expected_declaration_digest\"\xba\x01\n" + "\x16SourceOperationReceipt\x12\x1b\n" + "\teffect_id\x18\x01 \x01(\tR\beffectId\x12!\n" + "\fcommitted_at\x18\x02 \x01(\tR\vcommittedAt\x12\x16\n" + @@ -8442,6 +8455,7 @@ func file_saas_accounts_v1_datasource_proto_init() { (*AddSourceRequest_CollectionLabel)(nil), } file_saas_accounts_v1_datasource_proto_msgTypes[64].OneofWrappers = []any{} + file_saas_accounts_v1_datasource_proto_msgTypes[85].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/gen/saas/accounts/v1/installations.pb.go b/gen/saas/accounts/v1/installations.pb.go index 20eaeab..58f2110 100644 --- a/gen/saas/accounts/v1/installations.pb.go +++ b/gen/saas/accounts/v1/installations.pb.go @@ -8,6 +8,7 @@ package accountsv1 import ( _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + v1 "github.com/codefly-dev/saas-sdk-go/gen/host/installation/v1" _ "github.com/codefly-dev/saas-sdk-go/gen/saas/policy/v1" _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -404,6 +405,8 @@ type Installation struct { // Why the install step failed: the solution's bounded refusal reason, or a // fixed reason when it never answered. Empty unless status is FAILED. FailureReason string `protobuf:"bytes,13,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + // Current consent/lifecycle revision, for an explicit re-install approval. + Revision uint64 `protobuf:"varint,14,opt,name=revision,proto3" json:"revision,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -522,6 +525,13 @@ func (x *Installation) GetFailureReason() string { return "" } +func (x *Installation) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + type InstallSolutionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` @@ -572,7 +582,9 @@ type InstallSolutionRequest struct { // artifact_policies, with the same shapes as the module envelope grant. // Must be a subset of the current ceiling. Omitted selects that ceiling; // an explicit {} grants nothing. Tenant and identity are never scope fields. - Scope *string `protobuf:"bytes,13,opt,name=scope,proto3,oneof" json:"scope,omitempty"` + Scope *string `protobuf:"bytes,13,opt,name=scope,proto3,oneof" json:"scope,omitempty"` + // Required: the exact offer and installation state reviewed by the admin. + Approval *v1.ConsentApproval `protobuf:"bytes,14,opt,name=approval,proto3" json:"approval,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -684,6 +696,13 @@ func (x *InstallSolutionRequest) GetScope() string { return "" } +func (x *InstallSolutionRequest) GetApproval() *v1.ConsentApproval { + if x != nil { + return x.Approval + } + return nil +} + // An org administrator may only remove installed authority. The host reads // the current revision and serializes the narrowing with other lifecycle acts. type NarrowInstallationRequest struct { @@ -2238,7 +2257,7 @@ var File_saas_accounts_v1_installations_proto protoreflect.FileDescriptor const file_saas_accounts_v1_installations_proto_rawDesc = "" + "\n" + - "$saas/accounts/v1/installations.proto\x12\x10saas.accounts.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$saas/accounts/v1/authorization.proto\x1a\x1csaas/policy/v1/options.proto\"\x94\x05\n" + + "$saas/accounts/v1/installations.proto\x12\x10saas.accounts.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a'host/installation/v1/installation.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$saas/accounts/v1/authorization.proto\x1a\x1csaas/policy/v1/options.proto\"\xb0\x05\n" + "\fInstallation\x12\x18\n" + "\x02id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x1f\n" + "\x06org_id\x18\x02 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x05orgId\x126\n" + @@ -2254,8 +2273,9 @@ const file_saas_accounts_v1_installations_proto_rawDesc = "" + " \x01(\v2\x1a.google.protobuf.TimestampH\x00R\trevokedAt\x88\x01\x01\x12(\n" + "\ttarget_id\x18\v \x01(\tB\v\xbaH\b\xd8\x01\x01r\x03\xb0\x01\x01R\btargetId\x12/\n" + "\x0erevoked_reason\x18\f \x01(\tB\b\xbaH\x05r\x03\x18\x80\x04R\rrevokedReason\x12/\n" + - "\x0efailure_reason\x18\r \x01(\tB\b\xbaH\x05r\x03\x18\x80\x04R\rfailureReasonB\r\n" + - "\v_revoked_atJ\x04\b\x04\x10\x05R\x13solution_identifier\"\xf6\x04\n" + + "\x0efailure_reason\x18\r \x01(\tB\b\xbaH\x05r\x03\x18\x80\x04R\rfailureReason\x12\x1a\n" + + "\brevision\x18\x0e \x01(\x04R\brevisionB\r\n" + + "\v_revoked_atJ\x04\b\x04\x10\x05R\x13solution_identifier\"\xb9\x05\n" + "\x16InstallSolutionRequest\x12\x1f\n" + "\x06org_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x05orgId\x125\n" + "\x10agent_identifier\x18\x02 \x01(\tB\n" + @@ -2269,7 +2289,8 @@ const file_saas_accounts_v1_installations_proto_rawDesc = "" + " \x03(\tB\x0f\xbaH\f\x92\x01\t\x10@\"\x05r\x03\x18\x80\x04R\x10allowedAudiences\x126\n" + "\x0eallowed_scopes\x18\v \x03(\tB\x0f\xbaH\f\x92\x01\t\x10@\"\x05r\x03\x18\x80\x01R\rallowedScopes\x12%\n" + "\ttarget_id\x18\f \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\btargetId\x12&\n" + - "\x05scope\x18\r \x01(\tB\v\xbaH\br\x06\x10\x02(\x80\x80@H\x00R\x05scope\x88\x01\x01B\b\n" + + "\x05scope\x18\r \x01(\tB\v\xbaH\br\x06\x10\x02(\x80\x80@H\x00R\x05scope\x88\x01\x01\x12A\n" + + "\bapproval\x18\x0e \x01(\v2%.host.installation.v1.ConsentApprovalR\bapprovalB\b\n" + "\x06_scopeJ\x04\b\x03\x10\x04J\x04\b\x05\x10\x06R\x13solution_identifierR\x0froot_scope_path\"\x92\x01\n" + "\x19NarrowInstallationRequest\x12\x1f\n" + "\x06org_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x05orgId\x121\n" + @@ -2496,63 +2517,65 @@ var file_saas_accounts_v1_installations_proto_goTypes = []any{ (*ListAvailableSolutionsRequest)(nil), // 27: saas.accounts.v1.ListAvailableSolutionsRequest (*ListAvailableSolutionsResponse)(nil), // 28: saas.accounts.v1.ListAvailableSolutionsResponse (*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp - (*CollectionReadGrant)(nil), // 30: saas.accounts.v1.CollectionReadGrant - (*ScopeGrant)(nil), // 31: saas.accounts.v1.ScopeGrant - (*emptypb.Empty)(nil), // 32: google.protobuf.Empty + (*v1.ConsentApproval)(nil), // 30: host.installation.v1.ConsentApproval + (*CollectionReadGrant)(nil), // 31: saas.accounts.v1.CollectionReadGrant + (*ScopeGrant)(nil), // 32: saas.accounts.v1.ScopeGrant + (*emptypb.Empty)(nil), // 33: google.protobuf.Empty } var file_saas_accounts_v1_installations_proto_depIdxs = []int32{ 0, // 0: saas.accounts.v1.Installation.status:type_name -> saas.accounts.v1.InstallationStatus 29, // 1: saas.accounts.v1.Installation.created_at:type_name -> google.protobuf.Timestamp 29, // 2: saas.accounts.v1.Installation.revoked_at:type_name -> google.protobuf.Timestamp - 5, // 3: saas.accounts.v1.GetInstallationResponse.installation:type_name -> saas.accounts.v1.Installation - 1, // 4: saas.accounts.v1.GetInstallationResponse.health:type_name -> saas.accounts.v1.InstallationHealth - 0, // 5: saas.accounts.v1.ListInstallationsRequest.status:type_name -> saas.accounts.v1.InstallationStatus - 5, // 6: saas.accounts.v1.InstallationSummary.installation:type_name -> saas.accounts.v1.Installation - 1, // 7: saas.accounts.v1.InstallationSummary.health:type_name -> saas.accounts.v1.InstallationHealth - 14, // 8: saas.accounts.v1.ListInstallationsResponse.installations:type_name -> saas.accounts.v1.InstallationSummary - 5, // 9: saas.accounts.v1.OrganizationInstallation.installation:type_name -> saas.accounts.v1.Installation - 1, // 10: saas.accounts.v1.OrganizationInstallation.health:type_name -> saas.accounts.v1.InstallationHealth - 26, // 11: saas.accounts.v1.OrganizationInstallation.target:type_name -> saas.accounts.v1.AvailableSolution - 30, // 12: saas.accounts.v1.OrganizationInstallation.granted_teams:type_name -> saas.accounts.v1.CollectionReadGrant - 30, // 13: saas.accounts.v1.OrganizationInstallation.inherited_teams:type_name -> saas.accounts.v1.CollectionReadGrant - 19, // 14: saas.accounts.v1.OrganizationInstallation.readiness:type_name -> saas.accounts.v1.InstallationReadiness - 20, // 15: saas.accounts.v1.OrganizationInstallation.reached_modules:type_name -> saas.accounts.v1.ReachedModule - 2, // 16: saas.accounts.v1.ReadinessCondition.kind:type_name -> saas.accounts.v1.ReadinessConditionKind - 3, // 17: saas.accounts.v1.ReadinessCondition.cleared_by:type_name -> saas.accounts.v1.ReadinessClearedBy - 4, // 18: saas.accounts.v1.ReadinessCondition.action:type_name -> saas.accounts.v1.ReadinessAction - 18, // 19: saas.accounts.v1.InstallationReadiness.unmet:type_name -> saas.accounts.v1.ReadinessCondition - 17, // 20: saas.accounts.v1.ListOrganizationInstallationsResponse.installations:type_name -> saas.accounts.v1.OrganizationInstallation - 31, // 21: saas.accounts.v1.GrantInstallationToTeamResponse.grant:type_name -> saas.accounts.v1.ScopeGrant - 23, // 22: saas.accounts.v1.GrantInstallationToTeamResponse.carried:type_name -> saas.accounts.v1.CarriedModuleAccess - 18, // 23: saas.accounts.v1.GrantInstallationToTeamResponse.unmet:type_name -> saas.accounts.v1.ReadinessCondition - 26, // 24: saas.accounts.v1.ListAvailableSolutionsResponse.solutions:type_name -> saas.accounts.v1.AvailableSolution - 6, // 25: saas.accounts.v1.InstallationService.InstallSolution:input_type -> saas.accounts.v1.InstallSolutionRequest - 9, // 26: saas.accounts.v1.InstallationService.UninstallSolution:input_type -> saas.accounts.v1.UninstallSolutionRequest - 7, // 27: saas.accounts.v1.InstallationService.NarrowInstallation:input_type -> saas.accounts.v1.NarrowInstallationRequest - 8, // 28: saas.accounts.v1.InstallationService.RetryInstallation:input_type -> saas.accounts.v1.RetryInstallationRequest - 10, // 29: saas.accounts.v1.InstallationService.TransferInstallationOwnership:input_type -> saas.accounts.v1.TransferInstallationOwnershipRequest - 11, // 30: saas.accounts.v1.InstallationService.GetInstallation:input_type -> saas.accounts.v1.GetInstallationRequest - 13, // 31: saas.accounts.v1.InstallationService.ListInstallations:input_type -> saas.accounts.v1.ListInstallationsRequest - 27, // 32: saas.accounts.v1.InstallationService.ListAvailableSolutions:input_type -> saas.accounts.v1.ListAvailableSolutionsRequest - 16, // 33: saas.accounts.v1.InstallationService.ListOrganizationInstallations:input_type -> saas.accounts.v1.ListOrganizationInstallationsRequest - 22, // 34: saas.accounts.v1.InstallationService.GrantInstallationToTeam:input_type -> saas.accounts.v1.GrantInstallationToTeamRequest - 25, // 35: saas.accounts.v1.InstallationService.RevokeInstallationFromTeam:input_type -> saas.accounts.v1.RevokeInstallationFromTeamRequest - 5, // 36: saas.accounts.v1.InstallationService.InstallSolution:output_type -> saas.accounts.v1.Installation - 32, // 37: saas.accounts.v1.InstallationService.UninstallSolution:output_type -> google.protobuf.Empty - 32, // 38: saas.accounts.v1.InstallationService.NarrowInstallation:output_type -> google.protobuf.Empty - 5, // 39: saas.accounts.v1.InstallationService.RetryInstallation:output_type -> saas.accounts.v1.Installation - 5, // 40: saas.accounts.v1.InstallationService.TransferInstallationOwnership:output_type -> saas.accounts.v1.Installation - 12, // 41: saas.accounts.v1.InstallationService.GetInstallation:output_type -> saas.accounts.v1.GetInstallationResponse - 15, // 42: saas.accounts.v1.InstallationService.ListInstallations:output_type -> saas.accounts.v1.ListInstallationsResponse - 28, // 43: saas.accounts.v1.InstallationService.ListAvailableSolutions:output_type -> saas.accounts.v1.ListAvailableSolutionsResponse - 21, // 44: saas.accounts.v1.InstallationService.ListOrganizationInstallations:output_type -> saas.accounts.v1.ListOrganizationInstallationsResponse - 24, // 45: saas.accounts.v1.InstallationService.GrantInstallationToTeam:output_type -> saas.accounts.v1.GrantInstallationToTeamResponse - 32, // 46: saas.accounts.v1.InstallationService.RevokeInstallationFromTeam:output_type -> google.protobuf.Empty - 36, // [36:47] is the sub-list for method output_type - 25, // [25:36] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 30, // 3: saas.accounts.v1.InstallSolutionRequest.approval:type_name -> host.installation.v1.ConsentApproval + 5, // 4: saas.accounts.v1.GetInstallationResponse.installation:type_name -> saas.accounts.v1.Installation + 1, // 5: saas.accounts.v1.GetInstallationResponse.health:type_name -> saas.accounts.v1.InstallationHealth + 0, // 6: saas.accounts.v1.ListInstallationsRequest.status:type_name -> saas.accounts.v1.InstallationStatus + 5, // 7: saas.accounts.v1.InstallationSummary.installation:type_name -> saas.accounts.v1.Installation + 1, // 8: saas.accounts.v1.InstallationSummary.health:type_name -> saas.accounts.v1.InstallationHealth + 14, // 9: saas.accounts.v1.ListInstallationsResponse.installations:type_name -> saas.accounts.v1.InstallationSummary + 5, // 10: saas.accounts.v1.OrganizationInstallation.installation:type_name -> saas.accounts.v1.Installation + 1, // 11: saas.accounts.v1.OrganizationInstallation.health:type_name -> saas.accounts.v1.InstallationHealth + 26, // 12: saas.accounts.v1.OrganizationInstallation.target:type_name -> saas.accounts.v1.AvailableSolution + 31, // 13: saas.accounts.v1.OrganizationInstallation.granted_teams:type_name -> saas.accounts.v1.CollectionReadGrant + 31, // 14: saas.accounts.v1.OrganizationInstallation.inherited_teams:type_name -> saas.accounts.v1.CollectionReadGrant + 19, // 15: saas.accounts.v1.OrganizationInstallation.readiness:type_name -> saas.accounts.v1.InstallationReadiness + 20, // 16: saas.accounts.v1.OrganizationInstallation.reached_modules:type_name -> saas.accounts.v1.ReachedModule + 2, // 17: saas.accounts.v1.ReadinessCondition.kind:type_name -> saas.accounts.v1.ReadinessConditionKind + 3, // 18: saas.accounts.v1.ReadinessCondition.cleared_by:type_name -> saas.accounts.v1.ReadinessClearedBy + 4, // 19: saas.accounts.v1.ReadinessCondition.action:type_name -> saas.accounts.v1.ReadinessAction + 18, // 20: saas.accounts.v1.InstallationReadiness.unmet:type_name -> saas.accounts.v1.ReadinessCondition + 17, // 21: saas.accounts.v1.ListOrganizationInstallationsResponse.installations:type_name -> saas.accounts.v1.OrganizationInstallation + 32, // 22: saas.accounts.v1.GrantInstallationToTeamResponse.grant:type_name -> saas.accounts.v1.ScopeGrant + 23, // 23: saas.accounts.v1.GrantInstallationToTeamResponse.carried:type_name -> saas.accounts.v1.CarriedModuleAccess + 18, // 24: saas.accounts.v1.GrantInstallationToTeamResponse.unmet:type_name -> saas.accounts.v1.ReadinessCondition + 26, // 25: saas.accounts.v1.ListAvailableSolutionsResponse.solutions:type_name -> saas.accounts.v1.AvailableSolution + 6, // 26: saas.accounts.v1.InstallationService.InstallSolution:input_type -> saas.accounts.v1.InstallSolutionRequest + 9, // 27: saas.accounts.v1.InstallationService.UninstallSolution:input_type -> saas.accounts.v1.UninstallSolutionRequest + 7, // 28: saas.accounts.v1.InstallationService.NarrowInstallation:input_type -> saas.accounts.v1.NarrowInstallationRequest + 8, // 29: saas.accounts.v1.InstallationService.RetryInstallation:input_type -> saas.accounts.v1.RetryInstallationRequest + 10, // 30: saas.accounts.v1.InstallationService.TransferInstallationOwnership:input_type -> saas.accounts.v1.TransferInstallationOwnershipRequest + 11, // 31: saas.accounts.v1.InstallationService.GetInstallation:input_type -> saas.accounts.v1.GetInstallationRequest + 13, // 32: saas.accounts.v1.InstallationService.ListInstallations:input_type -> saas.accounts.v1.ListInstallationsRequest + 27, // 33: saas.accounts.v1.InstallationService.ListAvailableSolutions:input_type -> saas.accounts.v1.ListAvailableSolutionsRequest + 16, // 34: saas.accounts.v1.InstallationService.ListOrganizationInstallations:input_type -> saas.accounts.v1.ListOrganizationInstallationsRequest + 22, // 35: saas.accounts.v1.InstallationService.GrantInstallationToTeam:input_type -> saas.accounts.v1.GrantInstallationToTeamRequest + 25, // 36: saas.accounts.v1.InstallationService.RevokeInstallationFromTeam:input_type -> saas.accounts.v1.RevokeInstallationFromTeamRequest + 5, // 37: saas.accounts.v1.InstallationService.InstallSolution:output_type -> saas.accounts.v1.Installation + 33, // 38: saas.accounts.v1.InstallationService.UninstallSolution:output_type -> google.protobuf.Empty + 33, // 39: saas.accounts.v1.InstallationService.NarrowInstallation:output_type -> google.protobuf.Empty + 5, // 40: saas.accounts.v1.InstallationService.RetryInstallation:output_type -> saas.accounts.v1.Installation + 5, // 41: saas.accounts.v1.InstallationService.TransferInstallationOwnership:output_type -> saas.accounts.v1.Installation + 12, // 42: saas.accounts.v1.InstallationService.GetInstallation:output_type -> saas.accounts.v1.GetInstallationResponse + 15, // 43: saas.accounts.v1.InstallationService.ListInstallations:output_type -> saas.accounts.v1.ListInstallationsResponse + 28, // 44: saas.accounts.v1.InstallationService.ListAvailableSolutions:output_type -> saas.accounts.v1.ListAvailableSolutionsResponse + 21, // 45: saas.accounts.v1.InstallationService.ListOrganizationInstallations:output_type -> saas.accounts.v1.ListOrganizationInstallationsResponse + 24, // 46: saas.accounts.v1.InstallationService.GrantInstallationToTeam:output_type -> saas.accounts.v1.GrantInstallationToTeamResponse + 33, // 47: saas.accounts.v1.InstallationService.RevokeInstallationFromTeam:output_type -> google.protobuf.Empty + 37, // [37:48] is the sub-list for method output_type + 26, // [26:37] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_saas_accounts_v1_installations_proto_init() } diff --git a/gen/saas/accounts/v1/module_capabilities.pb.go b/gen/saas/accounts/v1/module_capabilities.pb.go index dd7c172..dc83425 100644 --- a/gen/saas/accounts/v1/module_capabilities.pb.go +++ b/gen/saas/accounts/v1/module_capabilities.pb.go @@ -3942,13 +3942,17 @@ func (x *CollectionSyncProvenance) GetRequestedByLabel() string { return "" } -// Tenant and viewer come exclusively from the verified Work Context. +// The calling module authenticates with its own module Work Context in the +// x-codefly-work-context header; the viewer it reads for travels here, and +// must be addressed to that module. Tenant and viewer come exclusively from +// the verified viewer Work Context. type ListReadableSourceCollectionsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + ViewerWorkContextToken string `protobuf:"bytes,3,opt,name=viewer_work_context_token,json=viewerWorkContextToken,proto3" json:"viewer_work_context_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListReadableSourceCollectionsRequest) Reset() { @@ -3995,6 +3999,13 @@ func (x *ListReadableSourceCollectionsRequest) GetPageToken() string { return "" } +func (x *ListReadableSourceCollectionsRequest) GetViewerWorkContextToken() string { + if x != nil { + return x.ViewerWorkContextToken + } + return "" +} + type ListReadableSourceCollectionsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Collections []*ReadableSourceCollection `protobuf:"bytes,1,rep,name=collections,proto3" json:"collections,omitempty"` @@ -4193,15 +4204,19 @@ func (x *ModulePlaceRecordResponse) GetNodeId() string { return "" } -// Exact-record delegated oracle. Tenant and subjects come only from the signed -// forwarded Work Context; a caller cannot provide a scope path or principal. +// Exact-record delegated oracle. The calling module authenticates with its +// own module Work Context in the x-codefly-work-context header; the viewer it +// asks for travels here, and must be addressed to that module. Tenant and +// subjects come only from the signed viewer Work Context; a caller cannot +// provide a scope path or principal. type CheckWorkContextRecordAccessRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - ResourceId string `protobuf:"bytes,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + ResourceId string `protobuf:"bytes,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` + ViewerWorkContextToken string `protobuf:"bytes,4,opt,name=viewer_work_context_token,json=viewerWorkContextToken,proto3" json:"viewer_work_context_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CheckWorkContextRecordAccessRequest) Reset() { @@ -4255,6 +4270,13 @@ func (x *CheckWorkContextRecordAccessRequest) GetAction() string { return "" } +func (x *CheckWorkContextRecordAccessRequest) GetViewerWorkContextToken() string { + if x != nil { + return x.ViewerWorkContextToken + } + return "" +} + type CheckWorkContextRecordAccessResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // False also covers an unplaced or inaccessible record; no scope is disclosed. @@ -6208,12 +6230,13 @@ const file_saas_accounts_v1_module_capabilities_proto_rawDesc = "" + "\atrigger\x18\x04 \x01(\tR\atrigger\x12W\n" + "\x14requester_disclosure\x18\x05 \x01(\x0e2$.saas.accounts.v1.MetadataDisclosureR\x13requesterDisclosure\x12=\n" + "\frequested_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vrequestedAt\x12,\n" + - "\x12requested_by_label\x18\a \x01(\tR\x10requestedByLabel\"x\n" + + "\x12requested_by_label\x18\a \x01(\tR\x10requestedByLabel\"\xc0\x01\n" + "$ListReadableSourceCollectionsRequest\x12'\n" + "\tpage_size\x18\x01 \x01(\x05B\n" + "\xbaH\a\x1a\x05\x18\xe8\a(\x00R\bpageSize\x12'\n" + "\n" + - "page_token\x18\x02 \x01(\tB\b\xbaH\x05r\x03\x18\x80\x10R\tpageToken\"\x9d\x01\n" + + "page_token\x18\x02 \x01(\tB\b\xbaH\x05r\x03\x18\x80\x10R\tpageToken\x12F\n" + + "\x19viewer_work_context_token\x18\x03 \x01(\tB\v\xbaH\br\x06\x10\x01\x18\x80\x80\x02R\x16viewerWorkContextToken\"\x9d\x01\n" + "%ListReadableSourceCollectionsResponse\x12L\n" + "\vcollections\x18\x01 \x03(\v2*.saas.accounts.v1.ReadableSourceCollectionR\vcollections\x12&\n" + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xa3\x02\n" + @@ -6229,7 +6252,7 @@ const file_saas_accounts_v1_module_capabilities_proto_rawDesc = "" + "\xbaH\ar\x05\x10\x01\x18\x80\x04R\n" + "resourceId\">\n" + "\x19ModulePlaceRecordResponse\x12!\n" + - "\anode_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x06nodeId\"\xa7\x01\n" + + "\anode_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x06nodeId\"\xef\x01\n" + "#CheckWorkContextRecordAccessRequest\x12/\n" + "\rresource_type\x18\x01 \x01(\tB\n" + "\xbaH\ar\x05\x10\x01\x18\x80\x02R\fresourceType\x12+\n" + @@ -6237,7 +6260,8 @@ const file_saas_accounts_v1_module_capabilities_proto_rawDesc = "" + "\xbaH\ar\x05\x10\x01\x18\x80\x04R\n" + "resourceId\x12\"\n" + "\x06action\x18\x03 \x01(\tB\n" + - "\xbaH\ar\x05\x10\x01\x18\x80\x02R\x06action\"d\n" + + "\xbaH\ar\x05\x10\x01\x18\x80\x02R\x06action\x12F\n" + + "\x19viewer_work_context_token\x18\x04 \x01(\tB\v\xbaH\br\x06\x10\x01\x18\x80\x80\x02R\x16viewerWorkContextToken\"d\n" + "$CheckWorkContextRecordAccessResponse\x12\x18\n" + "\aallowed\x18\x01 \x01(\bR\aallowed\x12\"\n" + "\rscope_node_id\x18\x02 \x01(\tR\vscopeNodeId\"\x9f\x01\n" + diff --git a/gen/saas/accounts/v1/work_contexts.pb.go b/gen/saas/accounts/v1/work_contexts.pb.go index a44e74d..d110c08 100644 --- a/gen/saas/accounts/v1/work_contexts.pb.go +++ b/gen/saas/accounts/v1/work_contexts.pb.go @@ -172,9 +172,16 @@ type StartTaskWorkContextRequest struct { // capability to this exact workspace and reject cross-workspace reuse. WorkspaceId *string `protobuf:"bytes,9,opt,name=workspace_id,json=workspaceId,proto3,oneof" json:"workspace_id,omitempty"` // Optional product/project attribution inside workspace_id. - ProjectId *string `protobuf:"bytes,10,opt,name=project_id,json=projectId,proto3,oneof" json:"project_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + ProjectId *string `protobuf:"bytes,10,opt,name=project_id,json=projectId,proto3,oneof" json:"project_id,omitempty"` + // Operation bindings of the audience module, by name, whose invoke scopes + // this capability carries beside authority_scopes. The host resolves each + // name to the binding as installed at org_id, narrowed by that installation + // exactly as the module's delegated exchange redeems it, and keeps each + // resource only if the person holds it. The caller names a binding and never + // its resource ids. A direct human-owned mint only. + OperationBindings []string `protobuf:"bytes,11,rep,name=operation_bindings,json=operationBindings,proto3" json:"operation_bindings,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *StartTaskWorkContextRequest) Reset() { @@ -270,6 +277,13 @@ func (x *StartTaskWorkContextRequest) GetProjectId() string { return "" } +func (x *StartTaskWorkContextRequest) GetOperationBindings() []string { + if x != nil { + return x.OperationBindings + } + return nil +} + // StartInstallationTaskRequest is the headless (no-user-present) mint path. The // caller is a trusted internal service (a job consumer leasing an ingest job), // not a bearer: owner := the installation's owner of record; actor := the agent @@ -1195,18 +1209,17 @@ var File_saas_accounts_v1_work_contexts_proto protoreflect.FileDescriptor const file_saas_accounts_v1_work_contexts_proto_rawDesc = "" + "\n" + - "$saas/accounts/v1/work_contexts.proto\x12\x10saas.accounts.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1csaas/policy/v1/options.proto\"\xad\x01\n" + + "$saas/accounts/v1/work_contexts.proto\x12\x10saas.accounts.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a3saas/accounts/v1/workload_operation_admission.proto\x1a\x1csaas/policy/v1/options.proto\"\xad\x01\n" + "\x10WorkContextScope\x12/\n" + "\rresource_kind\x18\x01 \x01(\tB\n" + "\xbaH\ar\x05\x10\x01\x18\x80\x01R\fresourceKind\x12/\n" + "\aactions\x18\x02 \x03(\tB\x15\xbaH\x12\x92\x01\x0f\b\x01\x10@\x18\x01\"\ar\x05\x10\x01\x18\x80\x01R\aactions\x127\n" + - "\fresource_ids\x18\x03 \x03(\tB\x14\xbaH\x11\x92\x01\x0e\x10\x80\x02\x18\x01\"\ar\x05\x10\x01\x18\x80\x04R\vresourceIds\"\xa8\x04\n" + + "\fresource_ids\x18\x03 \x03(\tB\x14\xbaH\x11\x92\x01\x0e\x10\x80\x02\x18\x01\"\ar\x05\x10\x01\x18\x80\x04R\vresourceIds\"\x88\x06\n" + "\x1bStartTaskWorkContextRequest\x12\x1f\n" + "\x06org_id\x18\x01 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\x05orgId\x12$\n" + "\atask_id\x18\x02 \x01(\tB\v\xbaH\b\xd8\x01\x01r\x03\xb0\x01\x01R\x06taskId\x12,\n" + - "\x12actor_principal_id\x18\x04 \x01(\tR\x10actorPrincipalId\x12Y\n" + - "\x10authority_scopes\x18\x05 \x03(\v2\".saas.accounts.v1.WorkContextScopeB\n" + - "\xbaH\a\x92\x01\x04\b\x01\x10@R\x0fauthorityScopes\x12&\n" + + "\x12actor_principal_id\x18\x04 \x01(\tR\x10actorPrincipalId\x12W\n" + + "\x10authority_scopes\x18\x05 \x03(\v2\".saas.accounts.v1.WorkContextScopeB\b\xbaH\x05\x92\x01\x02\x10@R\x0fauthorityScopes\x12&\n" + "\baudience\x18\x06 \x01(\tB\n" + "\xbaH\ar\x05\x10\x01\x18\x80\x04R\baudience\x12N\n" + "\rreplay_policy\x18\a \x01(\x0e2).saas.accounts.v1.WorkContextReplayPolicyR\freplayPolicy\x12+\n" + @@ -1218,7 +1231,9 @@ const file_saas_accounts_v1_work_contexts_proto_rawDesc = "" + "\n" + "project_id\x18\n" + " \x01(\tB\n" + - "\xbaH\ar\x05\x10\x01\x18\x80\x04H\x01R\tprojectId\x88\x01\x01B\x0f\n" + + "\xbaH\ar\x05\x10\x01\x18\x80\x04H\x01R\tprojectId\x88\x01\x01\x12B\n" + + "\x12operation_bindings\x18\v \x03(\tB\x13\xbaH\x10\x92\x01\r\x10@\x18\x01\"\ar\x05\x10\x01\x18\x80\x02R\x11operationBindings:\x9b\x01\xbaH\x97\x01\x1a\x94\x01\n" + + "\x18start_task.authority_ask\x122authority_scopes or operation_bindings is required\x1aDsize(this.authority_scopes) > 0 || size(this.operation_bindings) > 0B\x0f\n" + "\r_workspace_idB\r\n" + "\v_project_idJ\x04\b\x03\x10\x04R\n" + "session_id\"\xab\x04\n" + @@ -1345,11 +1360,12 @@ const file_saas_accounts_v1_work_contexts_proto_rawDesc = "" + "\x17WorkContextReplayPolicy\x12*\n" + "&WORK_CONTEXT_REPLAY_POLICY_UNSPECIFIED\x10\x00\x12)\n" + "%WORK_CONTEXT_REPLAY_POLICY_IDEMPOTENT\x10\x01\x12)\n" + - "%WORK_CONTEXT_REPLAY_POLICY_SINGLE_USE\x10\x022\xfb\f\n" + + "%WORK_CONTEXT_REPLAY_POLICY_SINGLE_USE\x10\x022\x93\x0e\n" + "\x12WorkContextService\x12\x83\x01\n" + "\x1aCheckAuthorizationRevision\x123.saas.accounts.v1.CheckAuthorizationRevisionRequest\x1a\x16.google.protobuf.Empty\"\x18\xc2\xf3\x18\x14\b\x03\x10\x010\x01:\x02\x10\x01@\x01H\aP\x03X\x03`\x01\x12y\n" + "\x15AuthorizeEvidenceRead\x12..saas.accounts.v1.AuthorizeEvidenceReadRequest\x1a\x16.google.protobuf.Empty\"\x18\xc2\xf3\x18\x14\b\x03\x10\x010\x01:\x02\x10\x01@\x01H\aP\x03X\x03`\x01\x12z\n" + - "\x10ConsumeSingleUse\x124.saas.accounts.v1.ConsumeSingleUseWorkContextRequest\x1a\x16.google.protobuf.Empty\"\x18\xc2\xf3\x18\x14\b\x03\x10\x010\x01:\x02\x10\x01@\x01H\aP\x03X\x03`\x01\x12\xca\x01\n" + + "\x10ConsumeSingleUse\x124.saas.accounts.v1.ConsumeSingleUseWorkContextRequest\x1a\x16.google.protobuf.Empty\"\x18\xc2\xf3\x18\x14\b\x03\x10\x010\x01:\x02\x10\x01@\x01H\aP\x03X\x03`\x01\x12\x95\x01\n" + + "\x16AdmitWorkloadOperation\x12/.saas.accounts.v1.AdmitWorkloadOperationRequest\x1a0.saas.accounts.v1.AdmitWorkloadOperationResponse\"\x18\xc2\xf3\x18\x14\b\x03\x10\x010\x01:\x02\x10\x01@\x01H\aP\x03X\x03`\x01\x12\xca\x01\n" + "\tStartTask\x12-.saas.accounts.v1.StartTaskWorkContextRequest\x1a#.saas.accounts.v1.IssuedWorkContext\"i\xc2\xf3\x18D\b\x02\x10\x03*\f\n" + "\x06org_id\x10\x02\x18\x010\x01:\"\n" + "\x1esaas.work_context.task_started\x10\x02@\x01H\x05P\x03X\x04`\x01x\x02\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/v1/work-contexts:task\x12\x86\x01\n" + @@ -1397,7 +1413,9 @@ var file_saas_accounts_v1_work_contexts_proto_goTypes = []any{ (*AuthorizeEvidenceReadRequest)(nil), // 11: saas.accounts.v1.AuthorizeEvidenceReadRequest (*ConsumeSingleUseWorkContextRequest)(nil), // 12: saas.accounts.v1.ConsumeSingleUseWorkContextRequest (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp - (*emptypb.Empty)(nil), // 14: google.protobuf.Empty + (*AdmitWorkloadOperationRequest)(nil), // 14: saas.accounts.v1.AdmitWorkloadOperationRequest + (*emptypb.Empty)(nil), // 15: google.protobuf.Empty + (*AdmitWorkloadOperationResponse)(nil), // 16: saas.accounts.v1.AdmitWorkloadOperationResponse } var file_saas_accounts_v1_work_contexts_proto_depIdxs = []int32{ 1, // 0: saas.accounts.v1.StartTaskWorkContextRequest.authority_scopes:type_name -> saas.accounts.v1.WorkContextScope @@ -1418,23 +1436,25 @@ var file_saas_accounts_v1_work_contexts_proto_depIdxs = []int32{ 10, // 15: saas.accounts.v1.WorkContextService.CheckAuthorizationRevision:input_type -> saas.accounts.v1.CheckAuthorizationRevisionRequest 11, // 16: saas.accounts.v1.WorkContextService.AuthorizeEvidenceRead:input_type -> saas.accounts.v1.AuthorizeEvidenceReadRequest 12, // 17: saas.accounts.v1.WorkContextService.ConsumeSingleUse:input_type -> saas.accounts.v1.ConsumeSingleUseWorkContextRequest - 2, // 18: saas.accounts.v1.WorkContextService.StartTask:input_type -> saas.accounts.v1.StartTaskWorkContextRequest - 3, // 19: saas.accounts.v1.WorkContextService.StartInstallationTask:input_type -> saas.accounts.v1.StartInstallationTaskRequest - 4, // 20: saas.accounts.v1.WorkContextService.StartRootSession:input_type -> saas.accounts.v1.StartRootSessionWorkContextRequest - 5, // 21: saas.accounts.v1.WorkContextService.ExchangeAudience:input_type -> saas.accounts.v1.ExchangeWorkContextAudienceRequest - 6, // 22: saas.accounts.v1.WorkContextService.StartChildSession:input_type -> saas.accounts.v1.StartChildSessionWorkContextRequest - 7, // 23: saas.accounts.v1.WorkContextService.RenewWorkContext:input_type -> saas.accounts.v1.RenewWorkContextRequest - 14, // 24: saas.accounts.v1.WorkContextService.CheckAuthorizationRevision:output_type -> google.protobuf.Empty - 14, // 25: saas.accounts.v1.WorkContextService.AuthorizeEvidenceRead:output_type -> google.protobuf.Empty - 14, // 26: saas.accounts.v1.WorkContextService.ConsumeSingleUse:output_type -> google.protobuf.Empty - 8, // 27: saas.accounts.v1.WorkContextService.StartTask:output_type -> saas.accounts.v1.IssuedWorkContext - 8, // 28: saas.accounts.v1.WorkContextService.StartInstallationTask:output_type -> saas.accounts.v1.IssuedWorkContext - 8, // 29: saas.accounts.v1.WorkContextService.StartRootSession:output_type -> saas.accounts.v1.IssuedWorkContext - 8, // 30: saas.accounts.v1.WorkContextService.ExchangeAudience:output_type -> saas.accounts.v1.IssuedWorkContext - 8, // 31: saas.accounts.v1.WorkContextService.StartChildSession:output_type -> saas.accounts.v1.IssuedWorkContext - 8, // 32: saas.accounts.v1.WorkContextService.RenewWorkContext:output_type -> saas.accounts.v1.IssuedWorkContext - 24, // [24:33] is the sub-list for method output_type - 15, // [15:24] is the sub-list for method input_type + 14, // 18: saas.accounts.v1.WorkContextService.AdmitWorkloadOperation:input_type -> saas.accounts.v1.AdmitWorkloadOperationRequest + 2, // 19: saas.accounts.v1.WorkContextService.StartTask:input_type -> saas.accounts.v1.StartTaskWorkContextRequest + 3, // 20: saas.accounts.v1.WorkContextService.StartInstallationTask:input_type -> saas.accounts.v1.StartInstallationTaskRequest + 4, // 21: saas.accounts.v1.WorkContextService.StartRootSession:input_type -> saas.accounts.v1.StartRootSessionWorkContextRequest + 5, // 22: saas.accounts.v1.WorkContextService.ExchangeAudience:input_type -> saas.accounts.v1.ExchangeWorkContextAudienceRequest + 6, // 23: saas.accounts.v1.WorkContextService.StartChildSession:input_type -> saas.accounts.v1.StartChildSessionWorkContextRequest + 7, // 24: saas.accounts.v1.WorkContextService.RenewWorkContext:input_type -> saas.accounts.v1.RenewWorkContextRequest + 15, // 25: saas.accounts.v1.WorkContextService.CheckAuthorizationRevision:output_type -> google.protobuf.Empty + 15, // 26: saas.accounts.v1.WorkContextService.AuthorizeEvidenceRead:output_type -> google.protobuf.Empty + 15, // 27: saas.accounts.v1.WorkContextService.ConsumeSingleUse:output_type -> google.protobuf.Empty + 16, // 28: saas.accounts.v1.WorkContextService.AdmitWorkloadOperation:output_type -> saas.accounts.v1.AdmitWorkloadOperationResponse + 8, // 29: saas.accounts.v1.WorkContextService.StartTask:output_type -> saas.accounts.v1.IssuedWorkContext + 8, // 30: saas.accounts.v1.WorkContextService.StartInstallationTask:output_type -> saas.accounts.v1.IssuedWorkContext + 8, // 31: saas.accounts.v1.WorkContextService.StartRootSession:output_type -> saas.accounts.v1.IssuedWorkContext + 8, // 32: saas.accounts.v1.WorkContextService.ExchangeAudience:output_type -> saas.accounts.v1.IssuedWorkContext + 8, // 33: saas.accounts.v1.WorkContextService.StartChildSession:output_type -> saas.accounts.v1.IssuedWorkContext + 8, // 34: saas.accounts.v1.WorkContextService.RenewWorkContext:output_type -> saas.accounts.v1.IssuedWorkContext + 25, // [25:35] is the sub-list for method output_type + 15, // [15:25] is the sub-list for method input_type 15, // [15:15] is the sub-list for extension type_name 15, // [15:15] is the sub-list for extension extendee 0, // [0:15] is the sub-list for field type_name @@ -1445,6 +1465,7 @@ func file_saas_accounts_v1_work_contexts_proto_init() { if File_saas_accounts_v1_work_contexts_proto != nil { return } + file_saas_accounts_v1_workload_operation_admission_proto_init() file_saas_accounts_v1_work_contexts_proto_msgTypes[1].OneofWrappers = []any{} file_saas_accounts_v1_work_contexts_proto_msgTypes[2].OneofWrappers = []any{} file_saas_accounts_v1_work_contexts_proto_msgTypes[6].OneofWrappers = []any{} diff --git a/gen/saas/accounts/v1/workload_operation_admission.pb.go b/gen/saas/accounts/v1/workload_operation_admission.pb.go new file mode 100644 index 0000000..7790148 --- /dev/null +++ b/gen/saas/accounts/v1/workload_operation_admission.pb.go @@ -0,0 +1,340 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: saas/accounts/v1/workload_operation_admission.proto + +package accountsv1 + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// WorkloadOperationRefusal is why a capability was not admitted. The gateway +// logs it and answers every refusal alike. +type WorkloadOperationRefusal int32 + +const ( + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_UNSPECIFIED WorkloadOperationRefusal = 0 + // Not a capability this issuer signed, inside its window, addressed to the + // alias; or the alias is one no operation context is minted for. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_NOT_INSPECTED WorkloadOperationRefusal = 1 + // Owned by a principal that is not a service: a person, an agent, or a kind + // this issuer does not name. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_OWNER_NOT_SERVICE WorkloadOperationRefusal = 2 + // A service principal's capability that is not shaped as a module operation + // context: it carries an actor chain, a grant hop, an operation binding, a + // parent session or an owner agent, names no authority scope, or has another + // replay policy or a longer window. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_NOT_OPERATION_CONTEXT WorkloadOperationRefusal = 3 + // Owned by the module principal the alias names: a module does not reach + // itself through this route. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_OWNER_IS_TARGET WorkloadOperationRefusal = 4 + // The owner is not a declared module principal, so no installation of its + // can stand behind the seal. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_SEAL_NOT_OWNERS WorkloadOperationRefusal = 5 + // The tenant has no ACTIVE installation of the route's target. The gateway + // answers this one 403, as it answers a person whose organization never + // installed the module. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_TARGET_NOT_INSTALLED WorkloadOperationRefusal = 6 + // The seal is one of the target's own installations: the caller would be the + // module it addresses. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_SEAL_ON_TARGET WorkloadOperationRefusal = 7 + // The issuer's live state has moved past the capability: its authorization + // revision is superseded, an epoch it carries has advanced, the seal names an + // installation the owner no longer holds, or the owner's module was + // uninstalled or now belongs to another tenant. + WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_NOT_CURRENT WorkloadOperationRefusal = 8 +) + +// Enum value maps for WorkloadOperationRefusal. +var ( + WorkloadOperationRefusal_name = map[int32]string{ + 0: "WORKLOAD_OPERATION_REFUSAL_UNSPECIFIED", + 1: "WORKLOAD_OPERATION_REFUSAL_NOT_INSPECTED", + 2: "WORKLOAD_OPERATION_REFUSAL_OWNER_NOT_SERVICE", + 3: "WORKLOAD_OPERATION_REFUSAL_NOT_OPERATION_CONTEXT", + 4: "WORKLOAD_OPERATION_REFUSAL_OWNER_IS_TARGET", + 5: "WORKLOAD_OPERATION_REFUSAL_SEAL_NOT_OWNERS", + 6: "WORKLOAD_OPERATION_REFUSAL_TARGET_NOT_INSTALLED", + 7: "WORKLOAD_OPERATION_REFUSAL_SEAL_ON_TARGET", + 8: "WORKLOAD_OPERATION_REFUSAL_NOT_CURRENT", + } + WorkloadOperationRefusal_value = map[string]int32{ + "WORKLOAD_OPERATION_REFUSAL_UNSPECIFIED": 0, + "WORKLOAD_OPERATION_REFUSAL_NOT_INSPECTED": 1, + "WORKLOAD_OPERATION_REFUSAL_OWNER_NOT_SERVICE": 2, + "WORKLOAD_OPERATION_REFUSAL_NOT_OPERATION_CONTEXT": 3, + "WORKLOAD_OPERATION_REFUSAL_OWNER_IS_TARGET": 4, + "WORKLOAD_OPERATION_REFUSAL_SEAL_NOT_OWNERS": 5, + "WORKLOAD_OPERATION_REFUSAL_TARGET_NOT_INSTALLED": 6, + "WORKLOAD_OPERATION_REFUSAL_SEAL_ON_TARGET": 7, + "WORKLOAD_OPERATION_REFUSAL_NOT_CURRENT": 8, + } +) + +func (x WorkloadOperationRefusal) Enum() *WorkloadOperationRefusal { + p := new(WorkloadOperationRefusal) + *p = x + return p +} + +func (x WorkloadOperationRefusal) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WorkloadOperationRefusal) Descriptor() protoreflect.EnumDescriptor { + return file_saas_accounts_v1_workload_operation_admission_proto_enumTypes[0].Descriptor() +} + +func (WorkloadOperationRefusal) Type() protoreflect.EnumType { + return &file_saas_accounts_v1_workload_operation_admission_proto_enumTypes[0] +} + +func (x WorkloadOperationRefusal) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WorkloadOperationRefusal.Descriptor instead. +func (WorkloadOperationRefusal) EnumDescriptor() ([]byte, []int) { + return file_saas_accounts_v1_workload_operation_admission_proto_rawDescGZIP(), []int{0} +} + +type AdmitWorkloadOperationRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The capability as presented, encoded. It is read back by its issuer, never + // verified as presented: nothing it carries is consumed. + WorkContext string `protobuf:"bytes,1,opt,name=work_context,json=workContext,proto3" json:"work_context,omitempty"` + // The route alias the gateway resolved from the request path. The capability + // must be addressed to it. + Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` + // The immutable solution target the route's alias resolved to, from the + // gateway's own routing. The tenant must have an ACTIVE installation of it. + TargetId string `protobuf:"bytes,3,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdmitWorkloadOperationRequest) Reset() { + *x = AdmitWorkloadOperationRequest{} + mi := &file_saas_accounts_v1_workload_operation_admission_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdmitWorkloadOperationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdmitWorkloadOperationRequest) ProtoMessage() {} + +func (x *AdmitWorkloadOperationRequest) ProtoReflect() protoreflect.Message { + mi := &file_saas_accounts_v1_workload_operation_admission_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdmitWorkloadOperationRequest.ProtoReflect.Descriptor instead. +func (*AdmitWorkloadOperationRequest) Descriptor() ([]byte, []int) { + return file_saas_accounts_v1_workload_operation_admission_proto_rawDescGZIP(), []int{0} +} + +func (x *AdmitWorkloadOperationRequest) GetWorkContext() string { + if x != nil { + return x.WorkContext + } + return "" +} + +func (x *AdmitWorkloadOperationRequest) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +func (x *AdmitWorkloadOperationRequest) GetTargetId() string { + if x != nil { + return x.TargetId + } + return "" +} + +type AdmitWorkloadOperationResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Admitted bool `protobuf:"varint,1,opt,name=admitted,proto3" json:"admitted,omitempty"` + // Set when admitted is false. + Refusal WorkloadOperationRefusal `protobuf:"varint,2,opt,name=refusal,proto3,enum=saas.accounts.v1.WorkloadOperationRefusal" json:"refusal,omitempty"` + // The signed facts the gateway logs and forwards, set only when admitted: + // the tenant, the installation the capability is sealed to (the CALLING + // module's), and the task. + TenantId string `protobuf:"bytes,3,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"` + InstallationId string `protobuf:"bytes,4,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"` + TaskId string `protobuf:"bytes,5,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdmitWorkloadOperationResponse) Reset() { + *x = AdmitWorkloadOperationResponse{} + mi := &file_saas_accounts_v1_workload_operation_admission_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdmitWorkloadOperationResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdmitWorkloadOperationResponse) ProtoMessage() {} + +func (x *AdmitWorkloadOperationResponse) ProtoReflect() protoreflect.Message { + mi := &file_saas_accounts_v1_workload_operation_admission_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdmitWorkloadOperationResponse.ProtoReflect.Descriptor instead. +func (*AdmitWorkloadOperationResponse) Descriptor() ([]byte, []int) { + return file_saas_accounts_v1_workload_operation_admission_proto_rawDescGZIP(), []int{1} +} + +func (x *AdmitWorkloadOperationResponse) GetAdmitted() bool { + if x != nil { + return x.Admitted + } + return false +} + +func (x *AdmitWorkloadOperationResponse) GetRefusal() WorkloadOperationRefusal { + if x != nil { + return x.Refusal + } + return WorkloadOperationRefusal_WORKLOAD_OPERATION_REFUSAL_UNSPECIFIED +} + +func (x *AdmitWorkloadOperationResponse) GetTenantId() string { + if x != nil { + return x.TenantId + } + return "" +} + +func (x *AdmitWorkloadOperationResponse) GetInstallationId() string { + if x != nil { + return x.InstallationId + } + return "" +} + +func (x *AdmitWorkloadOperationResponse) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +var File_saas_accounts_v1_workload_operation_admission_proto protoreflect.FileDescriptor + +const file_saas_accounts_v1_workload_operation_admission_proto_rawDesc = "" + + "\n" + + "3saas/accounts/v1/workload_operation_admission.proto\x12\x10saas.accounts.v1\x1a\x1bbuf/validate/validate.proto\"\x98\x01\n" + + "\x1dAdmitWorkloadOperationRequest\x12.\n" + + "\fwork_context\x18\x01 \x01(\tB\v\xbaH\br\x06\x10\x01\x18\x80\x80\x02R\vworkContext\x12 \n" + + "\x05alias\x18\x02 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x18\x80\x04R\x05alias\x12%\n" + + "\ttarget_id\x18\x03 \x01(\tB\b\xbaH\x05r\x03\xb0\x01\x01R\btargetId\"\xe1\x01\n" + + "\x1eAdmitWorkloadOperationResponse\x12\x1a\n" + + "\badmitted\x18\x01 \x01(\bR\badmitted\x12D\n" + + "\arefusal\x18\x02 \x01(\x0e2*.saas.accounts.v1.WorkloadOperationRefusalR\arefusal\x12\x1b\n" + + "\ttenant_id\x18\x03 \x01(\tR\btenantId\x12'\n" + + "\x0finstallation_id\x18\x04 \x01(\tR\x0einstallationId\x12\x17\n" + + "\atask_id\x18\x05 \x01(\tR\x06taskId*\xcc\x03\n" + + "\x18WorkloadOperationRefusal\x12*\n" + + "&WORKLOAD_OPERATION_REFUSAL_UNSPECIFIED\x10\x00\x12,\n" + + "(WORKLOAD_OPERATION_REFUSAL_NOT_INSPECTED\x10\x01\x120\n" + + ",WORKLOAD_OPERATION_REFUSAL_OWNER_NOT_SERVICE\x10\x02\x124\n" + + "0WORKLOAD_OPERATION_REFUSAL_NOT_OPERATION_CONTEXT\x10\x03\x12.\n" + + "*WORKLOAD_OPERATION_REFUSAL_OWNER_IS_TARGET\x10\x04\x12.\n" + + "*WORKLOAD_OPERATION_REFUSAL_SEAL_NOT_OWNERS\x10\x05\x123\n" + + "/WORKLOAD_OPERATION_REFUSAL_TARGET_NOT_INSTALLED\x10\x06\x12-\n" + + ")WORKLOAD_OPERATION_REFUSAL_SEAL_ON_TARGET\x10\a\x12*\n" + + "&WORKLOAD_OPERATION_REFUSAL_NOT_CURRENT\x10\bB\xdd\x01\n" + + "\x14com.saas.accounts.v1B\x1fWorkloadOperationAdmissionProtoP\x01ZBgithub.com/codefly-dev/saas-sdk-go/gen/saas/accounts/v1;accountsv1\xa2\x02\x03SAX\xaa\x02\x10Saas.Accounts.V1\xca\x02\x10Saas\\Accounts\\V1\xe2\x02\x1cSaas\\Accounts\\V1\\GPBMetadata\xea\x02\x12Saas::Accounts::V1b\x06proto3" + +var ( + file_saas_accounts_v1_workload_operation_admission_proto_rawDescOnce sync.Once + file_saas_accounts_v1_workload_operation_admission_proto_rawDescData []byte +) + +func file_saas_accounts_v1_workload_operation_admission_proto_rawDescGZIP() []byte { + file_saas_accounts_v1_workload_operation_admission_proto_rawDescOnce.Do(func() { + file_saas_accounts_v1_workload_operation_admission_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_saas_accounts_v1_workload_operation_admission_proto_rawDesc), len(file_saas_accounts_v1_workload_operation_admission_proto_rawDesc))) + }) + return file_saas_accounts_v1_workload_operation_admission_proto_rawDescData +} + +var file_saas_accounts_v1_workload_operation_admission_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_saas_accounts_v1_workload_operation_admission_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_saas_accounts_v1_workload_operation_admission_proto_goTypes = []any{ + (WorkloadOperationRefusal)(0), // 0: saas.accounts.v1.WorkloadOperationRefusal + (*AdmitWorkloadOperationRequest)(nil), // 1: saas.accounts.v1.AdmitWorkloadOperationRequest + (*AdmitWorkloadOperationResponse)(nil), // 2: saas.accounts.v1.AdmitWorkloadOperationResponse +} +var file_saas_accounts_v1_workload_operation_admission_proto_depIdxs = []int32{ + 0, // 0: saas.accounts.v1.AdmitWorkloadOperationResponse.refusal:type_name -> saas.accounts.v1.WorkloadOperationRefusal + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_saas_accounts_v1_workload_operation_admission_proto_init() } +func file_saas_accounts_v1_workload_operation_admission_proto_init() { + if File_saas_accounts_v1_workload_operation_admission_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_saas_accounts_v1_workload_operation_admission_proto_rawDesc), len(file_saas_accounts_v1_workload_operation_admission_proto_rawDesc)), + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_saas_accounts_v1_workload_operation_admission_proto_goTypes, + DependencyIndexes: file_saas_accounts_v1_workload_operation_admission_proto_depIdxs, + EnumInfos: file_saas_accounts_v1_workload_operation_admission_proto_enumTypes, + MessageInfos: file_saas_accounts_v1_workload_operation_admission_proto_msgTypes, + }.Build() + File_saas_accounts_v1_workload_operation_admission_proto = out.File + file_saas_accounts_v1_workload_operation_admission_proto_goTypes = nil + file_saas_accounts_v1_workload_operation_admission_proto_depIdxs = nil +} diff --git a/gen/saas/catalog/v1/catalog.pb.go b/gen/saas/catalog/v1/catalog.pb.go index bb3b40b..6040a38 100644 --- a/gen/saas/catalog/v1/catalog.pb.go +++ b/gen/saas/catalog/v1/catalog.pb.go @@ -659,9 +659,13 @@ type ServiceCatalog struct { Permissions []*PermissionDefinition `protobuf:"bytes,7,rep,name=permissions,proto3" json:"permissions,omitempty"` // entitlements is the sorted server-owned feature/quota vocabulary shared // by plans, runtime checks, generated clients, and plugin manifests. - Entitlements []*EntitlementDefinition `protobuf:"bytes,8,rep,name=entitlements,proto3" json:"entitlements,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + Entitlements []*EntitlementDefinition `protobuf:"bytes,8,rep,name=entitlements,proto3" json:"entitlements,omitempty"` + // Protobuf packages of the published interfaces this service implements, beside + // its own api_package. A method of one of these packages is served and + // catalogued like any other; its policy is the implementation's own sidecar. + InterfacePackages []string `protobuf:"bytes,9,rep,name=interface_packages,json=interfacePackages,proto3" json:"interface_packages,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServiceCatalog) Reset() { @@ -750,6 +754,13 @@ func (x *ServiceCatalog) GetEntitlements() []*EntitlementDefinition { return nil } +func (x *ServiceCatalog) GetInterfacePackages() []string { + if x != nil { + return x.InterfacePackages + } + return nil +} + // PermissionDefinition is one canonical resource:action capability. The // permission field is redundant by design: consumers can use it directly, // while validation proves it agrees with resource and action. @@ -2515,7 +2526,7 @@ var File_saas_catalog_v1_catalog_proto protoreflect.FileDescriptor const file_saas_catalog_v1_catalog_proto_rawDesc = "" + "\n" + - "\x1dsaas/catalog/v1/catalog.proto\x12\x0fsaas.catalog.v1\x1a\x1csaas/policy/v1/options.proto\"\xac\x03\n" + + "\x1dsaas/catalog/v1/catalog.proto\x12\x0fsaas.catalog.v1\x1a\x1csaas/policy/v1/options.proto\"\xdb\x03\n" + "\x0eServiceCatalog\x12%\n" + "\x0eschema_version\x18\x01 \x01(\tR\rschemaVersion\x123\n" + "\x05owner\x18\x02 \x01(\v2\x1d.saas.catalog.v1.ServiceOwnerR\x05owner\x12\x1f\n" + @@ -2526,7 +2537,8 @@ const file_saas_catalog_v1_catalog_proto_rawDesc = "" + "\bservices\x18\x05 \x03(\v2\x18.saas.catalog.v1.ServiceR\bservices\x121\n" + "\amethods\x18\x06 \x03(\v2\x17.saas.catalog.v1.MethodR\amethods\x12G\n" + "\vpermissions\x18\a \x03(\v2%.saas.catalog.v1.PermissionDefinitionR\vpermissions\x12J\n" + - "\fentitlements\x18\b \x03(\v2&.saas.catalog.v1.EntitlementDefinitionR\fentitlements\"\xd6\x01\n" + + "\fentitlements\x18\b \x03(\v2&.saas.catalog.v1.EntitlementDefinitionR\fentitlements\x12-\n" + + "\x12interface_packages\x18\t \x03(\tR\x11interfacePackages\"\xd6\x01\n" + "\x14PermissionDefinition\x12\x1e\n" + "\n" + "permission\x18\x01 \x01(\tR\n" + From 4a7f2c49b018ac98f110c7bd1f885de6b4a19435 Mon Sep 17 00:00:00 2001 From: crisfiorini-oss Date: Thu, 29 Oct 2026 16:23:17 +0000 Subject: [PATCH 2/2] fix(moduleauthority): isolate credentials by work item organization --- moduleauthority/client.go | 22 ++++++++++++++ moduleauthority/organization_test.go | 44 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 moduleauthority/organization_test.go diff --git a/moduleauthority/client.go b/moduleauthority/client.go index 0142fa1..ce4ef08 100644 --- a/moduleauthority/client.go +++ b/moduleauthority/client.go @@ -353,6 +353,28 @@ func (c *Client) Close() error { return nil } +// ForOrganization selects the organization of a work item without sharing a +// cached capability with another organization. The child shares this client's +// transports; Close on either releases idle connections, not active calls. +// Selection grants no authority: the host still proves the workload and its +// installation. A client already bound to an organization cannot switch it. +func (c *Client) ForOrganization(organization string) (*Client, error) { + if c == nil { + return nil, ErrInvalidCredentials + } + id, err := uuid.Parse(organization) + if err != nil || id.String() != organization || (c.credentials.OrganizationID != "" && c.credentials.OrganizationID != organization) { + return nil, ErrInvalidCredentials + } + if c.credentials.OrganizationID == organization { + return c, nil + } + credentials := c.credentials + credentials.OrganizationID = organization + return &Client{broker: c.broker, authority: c.authority, credentials: credentials, + now: c.now, refreshSkew: c.refreshSkew}, nil +} + // ModuleWorkContext returns a current module capability, refreshing it before // expiry. Concurrent callers share one refresh. func (c *Client) ModuleWorkContext(ctx context.Context) (string, error) { diff --git a/moduleauthority/organization_test.go b/moduleauthority/organization_test.go new file mode 100644 index 0000000..3a906f1 --- /dev/null +++ b/moduleauthority/organization_test.go @@ -0,0 +1,44 @@ +package moduleauthority + +import ( + "errors" + "testing" +) + +func TestOrganizationClientsNeverShareCapabilities(t *testing.T) { + h := newHost(t) + root := h.client(t, moduleCredentials) + organizations := []string{"11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222"} + for i, organization := range organizations { + child, err := root.ForOrganization(organization) + if err != nil { + t.Fatal(err) + } + for range 2 { + if _, err := child.ModuleWorkContext(t.Context()); err != nil { + t.Fatal(err) + } + } + if _, err := child.ForOrganization(organizations[1-i]); !errors.Is(err, ErrInvalidCredentials) { + t.Fatal("changed pinned organization") + } + } + _, _, bodies, _ := h.gateway.snapshot() + calls := bodies[hostWorkContextPath] + if len(calls) != 2 { + t.Fatalf("got %d mints, want one per organization", len(calls)) + } + for i, org := range organizations { + if calls[i]["organization_id"] != org { + t.Fatalf("mint %d: %v", i, calls[i]) + } + } + if root.module != "" || root.credentials.OrganizationID != "" { + t.Fatal("scoping mutated root") + } + for _, org := range []string{"", "not-an-organization", "11111111111141118111111111111111"} { + if _, err := root.ForOrganization(org); !errors.Is(err, ErrInvalidCredentials) { + t.Fatalf("accepted malformed selector %q", org) + } + } +}