From 7ffd1b3250033be7610c0f99dcdff28453566515 Mon Sep 17 00:00:00 2001 From: Prashant Yadav Date: Mon, 23 Mar 2026 21:34:54 -0700 Subject: [PATCH 1/2] feat: add VaultJWTAuthEnabled feature gate and vault proto fields for JWT auth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add org_id and workflow_owner fields to CreateSecretsRequest, UpdateSecretsRequest, DeleteSecretsRequest, and ListSecretIdentifiersRequest proto messages. Add VaultJWTAuthEnabled boolean setting (default: false) to cresettings. No behavior change — new proto fields default to empty strings and the gate is off. Made-with: Cursor --- pkg/capabilities/actions/vault/messages.pb.go | 88 +++++++++++++++++-- pkg/capabilities/actions/vault/messages.proto | 8 ++ pkg/settings/cresettings/README.md | 1 + pkg/settings/cresettings/defaults.json | 1 + pkg/settings/cresettings/defaults.toml | 1 + pkg/settings/cresettings/settings.go | 2 + pkg/settings/cresettings/settings_test.go | 1 + 7 files changed, 94 insertions(+), 8 deletions(-) diff --git a/pkg/capabilities/actions/vault/messages.pb.go b/pkg/capabilities/actions/vault/messages.pb.go index 45b73b75f6..301a2dc9e7 100644 --- a/pkg/capabilities/actions/vault/messages.pb.go +++ b/pkg/capabilities/actions/vault/messages.pb.go @@ -579,6 +579,8 @@ type CreateSecretsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` EncryptedSecrets []*EncryptedSecret `protobuf:"bytes,2,rep,name=encrypted_secrets,json=encryptedSecrets,proto3" json:"encrypted_secrets,omitempty"` + OrgId string `protobuf:"bytes,3,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + WorkflowOwner string `protobuf:"bytes,4,opt,name=workflow_owner,json=workflowOwner,proto3" json:"workflow_owner,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -627,6 +629,20 @@ func (x *CreateSecretsRequest) GetEncryptedSecrets() []*EncryptedSecret { return nil } +func (x *CreateSecretsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *CreateSecretsRequest) GetWorkflowOwner() string { + if x != nil { + return x.WorkflowOwner + } + return "" +} + type CreateSecretResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Id *SecretIdentifier `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -735,6 +751,8 @@ type UpdateSecretsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` EncryptedSecrets []*EncryptedSecret `protobuf:"bytes,2,rep,name=encrypted_secrets,json=encryptedSecrets,proto3" json:"encrypted_secrets,omitempty"` + OrgId string `protobuf:"bytes,3,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + WorkflowOwner string `protobuf:"bytes,4,opt,name=workflow_owner,json=workflowOwner,proto3" json:"workflow_owner,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -783,6 +801,20 @@ func (x *UpdateSecretsRequest) GetEncryptedSecrets() []*EncryptedSecret { return nil } +func (x *UpdateSecretsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *UpdateSecretsRequest) GetWorkflowOwner() string { + if x != nil { + return x.WorkflowOwner + } + return "" +} + type UpdateSecretResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Id *SecretIdentifier `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -891,6 +923,8 @@ type DeleteSecretsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` Ids []*SecretIdentifier `protobuf:"bytes,2,rep,name=ids,proto3" json:"ids,omitempty"` + OrgId string `protobuf:"bytes,3,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + WorkflowOwner string `protobuf:"bytes,4,opt,name=workflow_owner,json=workflowOwner,proto3" json:"workflow_owner,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -939,6 +973,20 @@ func (x *DeleteSecretsRequest) GetIds() []*SecretIdentifier { return nil } +func (x *DeleteSecretsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *DeleteSecretsRequest) GetWorkflowOwner() string { + if x != nil { + return x.WorkflowOwner + } + return "" +} + type DeleteSecretResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Id *SecretIdentifier `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -1048,6 +1096,8 @@ type ListSecretIdentifiersRequest struct { RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` Namespace string `protobuf:"bytes,3,opt,name=namespace,proto3" json:"namespace,omitempty"` + OrgId string `protobuf:"bytes,4,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + WorkflowOwner string `protobuf:"bytes,5,opt,name=workflow_owner,json=workflowOwner,proto3" json:"workflow_owner,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1103,6 +1153,20 @@ func (x *ListSecretIdentifiersRequest) GetNamespace() string { return "" } +func (x *ListSecretIdentifiersRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *ListSecretIdentifiersRequest) GetWorkflowOwner() string { + if x != nil { + return x.WorkflowOwner + } + return "" +} + type ListSecretIdentifiersResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Identifiers []*SecretIdentifier `protobuf:"bytes,1,rep,name=identifiers,proto3" json:"identifiers,omitempty"` @@ -2203,42 +2267,50 @@ const file_capabilities_actions_vault_messages_proto_rawDesc = "" + "\tresponses\x18\x01 \x03(\v2\x15.vault.SecretResponseR\tresponses\"c\n" + "\x0fEncryptedSecret\x12'\n" + "\x02id\x18\x01 \x01(\v2\x17.vault.SecretIdentifierR\x02id\x12'\n" + - "\x0fencrypted_value\x18\x02 \x01(\tR\x0eencryptedValue\"z\n" + + "\x0fencrypted_value\x18\x02 \x01(\tR\x0eencryptedValue\"\xb8\x01\n" + "\x14CreateSecretsRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12C\n" + - "\x11encrypted_secrets\x18\x02 \x03(\v2\x16.vault.EncryptedSecretR\x10encryptedSecrets\"o\n" + + "\x11encrypted_secrets\x18\x02 \x03(\v2\x16.vault.EncryptedSecretR\x10encryptedSecrets\x12\x15\n" + + "\x06org_id\x18\x03 \x01(\tR\x05orgId\x12%\n" + + "\x0eworkflow_owner\x18\x04 \x01(\tR\rworkflowOwner\"o\n" + "\x14CreateSecretResponse\x12'\n" + "\x02id\x18\x01 \x01(\v2\x17.vault.SecretIdentifierR\x02id\x12\x18\n" + "\asuccess\x18\x02 \x01(\bR\asuccess\x12\x14\n" + "\x05error\x18\x03 \x01(\tR\x05error\"R\n" + "\x15CreateSecretsResponse\x129\n" + - "\tresponses\x18\x01 \x03(\v2\x1b.vault.CreateSecretResponseR\tresponses\"z\n" + + "\tresponses\x18\x01 \x03(\v2\x1b.vault.CreateSecretResponseR\tresponses\"\xb8\x01\n" + "\x14UpdateSecretsRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12C\n" + - "\x11encrypted_secrets\x18\x02 \x03(\v2\x16.vault.EncryptedSecretR\x10encryptedSecrets\"o\n" + + "\x11encrypted_secrets\x18\x02 \x03(\v2\x16.vault.EncryptedSecretR\x10encryptedSecrets\x12\x15\n" + + "\x06org_id\x18\x03 \x01(\tR\x05orgId\x12%\n" + + "\x0eworkflow_owner\x18\x04 \x01(\tR\rworkflowOwner\"o\n" + "\x14UpdateSecretResponse\x12'\n" + "\x02id\x18\x01 \x01(\v2\x17.vault.SecretIdentifierR\x02id\x12\x18\n" + "\asuccess\x18\x02 \x01(\bR\asuccess\x12\x14\n" + "\x05error\x18\x03 \x01(\tR\x05error\"R\n" + "\x15UpdateSecretsResponse\x129\n" + - "\tresponses\x18\x01 \x03(\v2\x1b.vault.UpdateSecretResponseR\tresponses\"`\n" + + "\tresponses\x18\x01 \x03(\v2\x1b.vault.UpdateSecretResponseR\tresponses\"\x9e\x01\n" + "\x14DeleteSecretsRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12)\n" + - "\x03ids\x18\x02 \x03(\v2\x17.vault.SecretIdentifierR\x03ids\"o\n" + + "\x03ids\x18\x02 \x03(\v2\x17.vault.SecretIdentifierR\x03ids\x12\x15\n" + + "\x06org_id\x18\x03 \x01(\tR\x05orgId\x12%\n" + + "\x0eworkflow_owner\x18\x04 \x01(\tR\rworkflowOwner\"o\n" + "\x14DeleteSecretResponse\x12'\n" + "\x02id\x18\x01 \x01(\v2\x17.vault.SecretIdentifierR\x02id\x12\x18\n" + "\asuccess\x18\x02 \x01(\bR\asuccess\x12\x14\n" + "\x05error\x18\x03 \x01(\tR\x05error\"R\n" + "\x15DeleteSecretsResponse\x129\n" + - "\tresponses\x18\x01 \x03(\v2\x1b.vault.DeleteSecretResponseR\tresponses\"q\n" + + "\tresponses\x18\x01 \x03(\v2\x1b.vault.DeleteSecretResponseR\tresponses\"\xaf\x01\n" + "\x1cListSecretIdentifiersRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x14\n" + "\x05owner\x18\x02 \x01(\tR\x05owner\x12\x1c\n" + - "\tnamespace\x18\x03 \x01(\tR\tnamespace\"\x8a\x01\n" + + "\tnamespace\x18\x03 \x01(\tR\tnamespace\x12\x15\n" + + "\x06org_id\x18\x04 \x01(\tR\x05orgId\x12%\n" + + "\x0eworkflow_owner\x18\x05 \x01(\tR\rworkflowOwner\"\x8a\x01\n" + "\x1dListSecretIdentifiersResponse\x129\n" + "\videntifiers\x18\x01 \x03(\v2\x17.vault.SecretIdentifierR\videntifiers\x12\x18\n" + "\asuccess\x18\x02 \x01(\bR\asuccess\x12\x14\n" + diff --git a/pkg/capabilities/actions/vault/messages.proto b/pkg/capabilities/actions/vault/messages.proto index 6fb18c03ca..7500cc340f 100644 --- a/pkg/capabilities/actions/vault/messages.proto +++ b/pkg/capabilities/actions/vault/messages.proto @@ -52,6 +52,8 @@ message EncryptedSecret { message CreateSecretsRequest { string request_id = 1; repeated EncryptedSecret encrypted_secrets = 2; + string org_id = 3; + string workflow_owner = 4; } message CreateSecretResponse { @@ -67,6 +69,8 @@ message CreateSecretsResponse { message UpdateSecretsRequest { string request_id = 1; repeated EncryptedSecret encrypted_secrets = 2; + string org_id = 3; + string workflow_owner = 4; } message UpdateSecretResponse { @@ -82,6 +86,8 @@ message UpdateSecretsResponse { message DeleteSecretsRequest { string request_id = 1; repeated SecretIdentifier ids = 2; + string org_id = 3; + string workflow_owner = 4; } message DeleteSecretResponse { @@ -98,6 +104,8 @@ message ListSecretIdentifiersRequest { string request_id = 1; string owner = 2; string namespace = 3; + string org_id = 4; + string workflow_owner = 5; } message ListSecretIdentifiersResponse { diff --git a/pkg/settings/cresettings/README.md b/pkg/settings/cresettings/README.md index 66ac96edb9..9a0cf7e432 100644 --- a/pkg/settings/cresettings/README.md +++ b/pkg/settings/cresettings/README.md @@ -36,6 +36,7 @@ flowchart subgraph handleRequest[httpServer/websocketServer.handleRequest] GatewayIncomingPayloadSizeLimit{{GatewayIncomingPayloadSizeLimit}}:::bound %% TODO GatewayVaultManagementEnabled + VaultJWTAuthEnabled[/VaultJWTAuthEnabled\]:::gate end subgraph HandleNodeMessage[gatewayHandler.HandleNodeMessage] diff --git a/pkg/settings/cresettings/defaults.json b/pkg/settings/cresettings/defaults.json index d3add960cd..7465c0f833 100644 --- a/pkg/settings/cresettings/defaults.json +++ b/pkg/settings/cresettings/defaults.json @@ -3,6 +3,7 @@ "WorkflowExecutionConcurrencyLimit": "200", "GatewayIncomingPayloadSizeLimit": "1mb", "GatewayVaultManagementEnabled": "true", + "VaultJWTAuthEnabled": "false", "GatewayHTTPGlobalRate": "500rps:500", "GatewayHTTPPerNodeRate": "100rps:100", "TriggerRegistrationStatusUpdateTimeout": "0s", diff --git a/pkg/settings/cresettings/defaults.toml b/pkg/settings/cresettings/defaults.toml index eff679a474..404683d876 100644 --- a/pkg/settings/cresettings/defaults.toml +++ b/pkg/settings/cresettings/defaults.toml @@ -2,6 +2,7 @@ WorkflowLimit = '200' WorkflowExecutionConcurrencyLimit = '200' GatewayIncomingPayloadSizeLimit = '1mb' GatewayVaultManagementEnabled = 'true' +VaultJWTAuthEnabled = 'false' GatewayHTTPGlobalRate = '500rps:500' GatewayHTTPPerNodeRate = '100rps:100' TriggerRegistrationStatusUpdateTimeout = '0s' diff --git a/pkg/settings/cresettings/settings.go b/pkg/settings/cresettings/settings.go index f506be7ed5..1ec0133619 100644 --- a/pkg/settings/cresettings/settings.go +++ b/pkg/settings/cresettings/settings.go @@ -56,6 +56,7 @@ var Default = Schema{ WorkflowExecutionConcurrencyLimit: Int(200), GatewayIncomingPayloadSizeLimit: Size(1 * config.MByte), GatewayVaultManagementEnabled: Bool(true), + VaultJWTAuthEnabled: Bool(false), GatewayHTTPGlobalRate: Rate(rate.Limit(500), 500), GatewayHTTPPerNodeRate: Rate(rate.Limit(100), 100), TriggerRegistrationStatusUpdateTimeout: Duration(0 * time.Second), @@ -216,6 +217,7 @@ type Schema struct { WorkflowExecutionConcurrencyLimit Setting[int] `unit:"{workflow}"` GatewayIncomingPayloadSizeLimit Setting[config.Size] GatewayVaultManagementEnabled Setting[bool] + VaultJWTAuthEnabled Setting[bool] GatewayHTTPGlobalRate Setting[config.Rate] GatewayHTTPPerNodeRate Setting[config.Rate] TriggerRegistrationStatusUpdateTimeout Setting[time.Duration] diff --git a/pkg/settings/cresettings/settings_test.go b/pkg/settings/cresettings/settings_test.go index e68f72ba24..f2599a9f34 100644 --- a/pkg/settings/cresettings/settings_test.go +++ b/pkg/settings/cresettings/settings_test.go @@ -122,6 +122,7 @@ func TestSchema_Unmarshal(t *testing.T) { assert.Equal(t, 500, cfg.WorkflowLimit.DefaultValue) assert.Equal(t, 14*config.KByte, cfg.GatewayIncomingPayloadSizeLimit.DefaultValue) assert.Equal(t, true, cfg.GatewayVaultManagementEnabled.DefaultValue) + assert.Equal(t, false, cfg.VaultJWTAuthEnabled.DefaultValue) assert.Equal(t, 48*time.Hour, cfg.PerOrg.ZeroBalancePruningTimeout.DefaultValue) assert.Equal(t, 99, cfg.PerOwner.WorkflowExecutionConcurrencyLimit.DefaultValue) assert.Equal(t, 250*config.MByte, cfg.PerWorkflow.WASMMemoryLimit.DefaultValue) From 37b54c306a1cce521e8c7629d7bddd8b8b995fa3 Mon Sep 17 00:00:00 2001 From: Prashant Yadav Date: Tue, 24 Mar 2026 23:18:32 -0700 Subject: [PATCH 2/2] feat: add VaultOrgIdAsSecretOwnerEnabled feature gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add VaultOrgIdAsSecretOwnerEnabled boolean setting (default: false) to cresettings, gating the upcoming org-id-as-secret-owner behavior for Vault requests. No behavior change — the gate defaults to off. Updated golden files (defaults.json, defaults.toml), README flowchart, and test assertions. Made-with: Cursor --- pkg/settings/cresettings/README.md | 1 + pkg/settings/cresettings/defaults.json | 1 + pkg/settings/cresettings/defaults.toml | 1 + pkg/settings/cresettings/settings.go | 2 ++ pkg/settings/cresettings/settings_test.go | 1 + 5 files changed, 6 insertions(+) diff --git a/pkg/settings/cresettings/README.md b/pkg/settings/cresettings/README.md index 9a0cf7e432..a06edfdc33 100644 --- a/pkg/settings/cresettings/README.md +++ b/pkg/settings/cresettings/README.md @@ -37,6 +37,7 @@ flowchart GatewayIncomingPayloadSizeLimit{{GatewayIncomingPayloadSizeLimit}}:::bound %% TODO GatewayVaultManagementEnabled VaultJWTAuthEnabled[/VaultJWTAuthEnabled\]:::gate + VaultOrgIdAsSecretOwnerEnabled[/VaultOrgIdAsSecretOwnerEnabled\]:::gate end subgraph HandleNodeMessage[gatewayHandler.HandleNodeMessage] diff --git a/pkg/settings/cresettings/defaults.json b/pkg/settings/cresettings/defaults.json index 7465c0f833..ba12cd4d64 100644 --- a/pkg/settings/cresettings/defaults.json +++ b/pkg/settings/cresettings/defaults.json @@ -4,6 +4,7 @@ "GatewayIncomingPayloadSizeLimit": "1mb", "GatewayVaultManagementEnabled": "true", "VaultJWTAuthEnabled": "false", + "VaultOrgIdAsSecretOwnerEnabled": "false", "GatewayHTTPGlobalRate": "500rps:500", "GatewayHTTPPerNodeRate": "100rps:100", "TriggerRegistrationStatusUpdateTimeout": "0s", diff --git a/pkg/settings/cresettings/defaults.toml b/pkg/settings/cresettings/defaults.toml index 404683d876..fa7a5e82b9 100644 --- a/pkg/settings/cresettings/defaults.toml +++ b/pkg/settings/cresettings/defaults.toml @@ -3,6 +3,7 @@ WorkflowExecutionConcurrencyLimit = '200' GatewayIncomingPayloadSizeLimit = '1mb' GatewayVaultManagementEnabled = 'true' VaultJWTAuthEnabled = 'false' +VaultOrgIdAsSecretOwnerEnabled = 'false' GatewayHTTPGlobalRate = '500rps:500' GatewayHTTPPerNodeRate = '100rps:100' TriggerRegistrationStatusUpdateTimeout = '0s' diff --git a/pkg/settings/cresettings/settings.go b/pkg/settings/cresettings/settings.go index 1ec0133619..888fb237d3 100644 --- a/pkg/settings/cresettings/settings.go +++ b/pkg/settings/cresettings/settings.go @@ -57,6 +57,7 @@ var Default = Schema{ GatewayIncomingPayloadSizeLimit: Size(1 * config.MByte), GatewayVaultManagementEnabled: Bool(true), VaultJWTAuthEnabled: Bool(false), + VaultOrgIdAsSecretOwnerEnabled: Bool(false), GatewayHTTPGlobalRate: Rate(rate.Limit(500), 500), GatewayHTTPPerNodeRate: Rate(rate.Limit(100), 100), TriggerRegistrationStatusUpdateTimeout: Duration(0 * time.Second), @@ -218,6 +219,7 @@ type Schema struct { GatewayIncomingPayloadSizeLimit Setting[config.Size] GatewayVaultManagementEnabled Setting[bool] VaultJWTAuthEnabled Setting[bool] + VaultOrgIdAsSecretOwnerEnabled Setting[bool] GatewayHTTPGlobalRate Setting[config.Rate] GatewayHTTPPerNodeRate Setting[config.Rate] TriggerRegistrationStatusUpdateTimeout Setting[time.Duration] diff --git a/pkg/settings/cresettings/settings_test.go b/pkg/settings/cresettings/settings_test.go index f2599a9f34..2792cb56c9 100644 --- a/pkg/settings/cresettings/settings_test.go +++ b/pkg/settings/cresettings/settings_test.go @@ -123,6 +123,7 @@ func TestSchema_Unmarshal(t *testing.T) { assert.Equal(t, 14*config.KByte, cfg.GatewayIncomingPayloadSizeLimit.DefaultValue) assert.Equal(t, true, cfg.GatewayVaultManagementEnabled.DefaultValue) assert.Equal(t, false, cfg.VaultJWTAuthEnabled.DefaultValue) + assert.Equal(t, false, cfg.VaultOrgIdAsSecretOwnerEnabled.DefaultValue) assert.Equal(t, 48*time.Hour, cfg.PerOrg.ZeroBalancePruningTimeout.DefaultValue) assert.Equal(t, 99, cfg.PerOwner.WorkflowExecutionConcurrencyLimit.DefaultValue) assert.Equal(t, 250*config.MByte, cfg.PerWorkflow.WASMMemoryLimit.DefaultValue)