diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go
index e562bbd1f7160..4c252e6d32c5b 100644
--- a/coderd/database/dbauthz/dbauthz_test.go
+++ b/coderd/database/dbauthz/dbauthz_test.go
@@ -3997,6 +3997,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Health: database.WorkspaceAppHealthDisabled,
SharingLevel: database.AppSharingLevelOwner,
OpenIn: database.WorkspaceAppOpenInSlimWindow,
+ CORSBehavior: database.AppCorsBehaviorSimple,
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
s.Run("InsertWorkspaceResourceMetadata", s.Subtest(func(db database.Store, check *expects) {
diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go
index 854c7c2974fe6..42cb8b3f7bef0 100644
--- a/coderd/database/dbgen/dbgen.go
+++ b/coderd/database/dbgen/dbgen.go
@@ -723,6 +723,7 @@ func WorkspaceApp(t testing.TB, db database.Store, orig database.WorkspaceApp) d
DisplayOrder: takeFirst(orig.DisplayOrder, 1),
Hidden: orig.Hidden,
OpenIn: takeFirst(orig.OpenIn, database.WorkspaceAppOpenInSlimWindow),
+ CORSBehavior: takeFirst(orig.CORSBehavior, database.AppCorsBehaviorSimple),
})
require.NoError(t, err, "insert app")
return resource
diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go
index 1359d2e63484d..899f92e2ee176 100644
--- a/coderd/database/dbmem/dbmem.go
+++ b/coderd/database/dbmem/dbmem.go
@@ -9701,6 +9701,10 @@ func (q *FakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
arg.OpenIn = database.WorkspaceAppOpenInSlimWindow
}
+ if arg.CORSBehavior == "" {
+ arg.CORSBehavior = database.AppCorsBehaviorSimple
+ }
+
// nolint:gosimple
workspaceApp := database.WorkspaceApp{
ID: arg.ID,
@@ -9721,6 +9725,7 @@ func (q *FakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
Hidden: arg.Hidden,
DisplayOrder: arg.DisplayOrder,
OpenIn: arg.OpenIn,
+ CORSBehavior: arg.CORSBehavior,
}
q.workspaceApps = append(q.workspaceApps, workspaceApp)
return workspaceApp, nil
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 83d998b2b9a3e..5b56820f46de9 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -10,6 +10,11 @@ CREATE TYPE api_key_scope AS ENUM (
'application_connect'
);
+CREATE TYPE app_cors_behavior AS ENUM (
+ 'simple',
+ 'passthru'
+);
+
CREATE TYPE app_sharing_level AS ENUM (
'owner',
'authenticated',
@@ -1933,7 +1938,8 @@ CREATE TABLE workspace_apps (
external boolean DEFAULT false NOT NULL,
display_order integer DEFAULT 0 NOT NULL,
hidden boolean DEFAULT false NOT NULL,
- open_in workspace_app_open_in DEFAULT 'slim-window'::workspace_app_open_in NOT NULL
+ open_in workspace_app_open_in DEFAULT 'slim-window'::workspace_app_open_in NOT NULL,
+ cors_behavior app_cors_behavior DEFAULT 'simple'::app_cors_behavior NOT NULL
);
COMMENT ON COLUMN workspace_apps.display_order IS 'Specifies the order in which to display agent app in user interfaces.';
diff --git a/coderd/database/migrations/000318_workspace_app_cors_behavior.down.sql b/coderd/database/migrations/000318_workspace_app_cors_behavior.down.sql
new file mode 100644
index 0000000000000..5f6e26306594e
--- /dev/null
+++ b/coderd/database/migrations/000318_workspace_app_cors_behavior.down.sql
@@ -0,0 +1,4 @@
+ALTER TABLE workspace_apps
+ DROP COLUMN IF EXISTS cors_behavior;
+
+DROP TYPE IF EXISTS app_cors_behavior;
\ No newline at end of file
diff --git a/coderd/database/migrations/000318_workspace_app_cors_behavior.up.sql b/coderd/database/migrations/000318_workspace_app_cors_behavior.up.sql
new file mode 100644
index 0000000000000..aab91bf4024e7
--- /dev/null
+++ b/coderd/database/migrations/000318_workspace_app_cors_behavior.up.sql
@@ -0,0 +1,10 @@
+CREATE TYPE app_cors_behavior AS ENUM (
+ 'simple',
+ 'passthru'
+);
+
+-- https://www.postgresql.org/docs/16/sql-altertable.html
+-- When a column is added with ADD COLUMN and a non-volatile DEFAULT is specified, the default is evaluated at the time
+-- of the statement and the result stored in the table's metadata. That value will be used for the column for all existing rows.
+ALTER TABLE workspace_apps
+ ADD COLUMN cors_behavior app_cors_behavior NOT NULL DEFAULT 'simple'::app_cors_behavior;
\ No newline at end of file
diff --git a/coderd/database/models.go b/coderd/database/models.go
index f817ff2712d54..a5c2dccd7a7c4 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -74,6 +74,64 @@ func AllAPIKeyScopeValues() []APIKeyScope {
}
}
+type AppCORSBehavior string
+
+const (
+ AppCorsBehaviorSimple AppCORSBehavior = "simple"
+ AppCorsBehaviorPassthru AppCORSBehavior = "passthru"
+)
+
+func (e *AppCORSBehavior) Scan(src interface{}) error {
+ switch s := src.(type) {
+ case []byte:
+ *e = AppCORSBehavior(s)
+ case string:
+ *e = AppCORSBehavior(s)
+ default:
+ return fmt.Errorf("unsupported scan type for AppCORSBehavior: %T", src)
+ }
+ return nil
+}
+
+type NullAppCORSBehavior struct {
+ AppCORSBehavior AppCORSBehavior `json:"app_cors_behavior"`
+ Valid bool `json:"valid"` // Valid is true if AppCORSBehavior is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAppCORSBehavior) Scan(value interface{}) error {
+ if value == nil {
+ ns.AppCORSBehavior, ns.Valid = "", false
+ return nil
+ }
+ ns.Valid = true
+ return ns.AppCORSBehavior.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAppCORSBehavior) Value() (driver.Value, error) {
+ if !ns.Valid {
+ return nil, nil
+ }
+ return string(ns.AppCORSBehavior), nil
+}
+
+func (e AppCORSBehavior) Valid() bool {
+ switch e {
+ case AppCorsBehaviorSimple,
+ AppCorsBehaviorPassthru:
+ return true
+ }
+ return false
+}
+
+func AllAppCORSBehaviorValues() []AppCORSBehavior {
+ return []AppCORSBehavior{
+ AppCorsBehaviorSimple,
+ AppCorsBehaviorPassthru,
+ }
+}
+
type AppSharingLevel string
const (
@@ -3527,8 +3585,9 @@ type WorkspaceApp struct {
// Specifies the order in which to display agent app in user interfaces.
DisplayOrder int32 `db:"display_order" json:"display_order"`
// Determines if the app is not shown in user interfaces.
- Hidden bool `db:"hidden" json:"hidden"`
- OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
+ Hidden bool `db:"hidden" json:"hidden"`
+ OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
+ CORSBehavior AppCORSBehavior `db:"cors_behavior" json:"cors_behavior"`
}
// Audit sessions for workspace apps, the data in this table is ephemeral and is used to deduplicate audit log entries for workspace apps. While a session is active, the same data will not be logged again. This table does not store historical data.
diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go
index 60416b1a35730..afc9987c6ac46 100644
--- a/coderd/database/queries.sql.go
+++ b/coderd/database/queries.sql.go
@@ -15646,7 +15646,7 @@ func (q *sqlQuerier) GetLatestWorkspaceAppStatusesByWorkspaceIDs(ctx context.Con
}
const getWorkspaceAppByAgentIDAndSlug = `-- name: GetWorkspaceAppByAgentIDAndSlug :one
-SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 AND slug = $2
+SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, cors_behavior FROM workspace_apps WHERE agent_id = $1 AND slug = $2
`
type GetWorkspaceAppByAgentIDAndSlugParams struct {
@@ -15676,6 +15676,7 @@ func (q *sqlQuerier) GetWorkspaceAppByAgentIDAndSlug(ctx context.Context, arg Ge
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
+ &i.CORSBehavior,
)
return i, err
}
@@ -15717,7 +15718,7 @@ func (q *sqlQuerier) GetWorkspaceAppStatusesByAppIDs(ctx context.Context, ids []
}
const getWorkspaceAppsByAgentID = `-- name: GetWorkspaceAppsByAgentID :many
-SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
+SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, cors_behavior FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid.UUID) ([]WorkspaceApp, error) {
@@ -15748,6 +15749,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
+ &i.CORSBehavior,
); err != nil {
return nil, err
}
@@ -15763,7 +15765,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
}
const getWorkspaceAppsByAgentIDs = `-- name: GetWorkspaceAppsByAgentIDs :many
-SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
+SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, cors_behavior FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceApp, error) {
@@ -15794,6 +15796,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
+ &i.CORSBehavior,
); err != nil {
return nil, err
}
@@ -15809,7 +15812,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
}
const getWorkspaceAppsCreatedAfter = `-- name: GetWorkspaceAppsCreatedAfter :many
-SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
+SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, cors_behavior FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceApp, error) {
@@ -15840,6 +15843,7 @@ func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
+ &i.CORSBehavior,
); err != nil {
return nil, err
}
@@ -15868,6 +15872,7 @@ INSERT INTO
external,
subdomain,
sharing_level,
+ cors_behavior,
healthcheck_url,
healthcheck_interval,
healthcheck_threshold,
@@ -15877,7 +15882,7 @@ INSERT INTO
open_in
)
VALUES
- ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in
+ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, cors_behavior
`
type InsertWorkspaceAppParams struct {
@@ -15892,6 +15897,7 @@ type InsertWorkspaceAppParams struct {
External bool `db:"external" json:"external"`
Subdomain bool `db:"subdomain" json:"subdomain"`
SharingLevel AppSharingLevel `db:"sharing_level" json:"sharing_level"`
+ CORSBehavior AppCORSBehavior `db:"cors_behavior" json:"cors_behavior"`
HealthcheckUrl string `db:"healthcheck_url" json:"healthcheck_url"`
HealthcheckInterval int32 `db:"healthcheck_interval" json:"healthcheck_interval"`
HealthcheckThreshold int32 `db:"healthcheck_threshold" json:"healthcheck_threshold"`
@@ -15914,6 +15920,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
arg.External,
arg.Subdomain,
arg.SharingLevel,
+ arg.CORSBehavior,
arg.HealthcheckUrl,
arg.HealthcheckInterval,
arg.HealthcheckThreshold,
@@ -15942,6 +15949,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
+ &i.CORSBehavior,
)
return i, err
}
diff --git a/coderd/database/queries/workspaceapps.sql b/coderd/database/queries/workspaceapps.sql
index cd1cddb454b88..b41fa88e5879a 100644
--- a/coderd/database/queries/workspaceapps.sql
+++ b/coderd/database/queries/workspaceapps.sql
@@ -24,6 +24,7 @@ INSERT INTO
external,
subdomain,
sharing_level,
+ cors_behavior,
healthcheck_url,
healthcheck_interval,
healthcheck_threshold,
@@ -33,7 +34,7 @@ INSERT INTO
open_in
)
VALUES
- ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING *;
+ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING *;
-- name: UpdateWorkspaceAppHealthByID :exec
UPDATE
diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml
index b43281a3f1051..96a0142222bf0 100644
--- a/coderd/database/sqlc.yaml
+++ b/coderd/database/sqlc.yaml
@@ -147,6 +147,8 @@ sql:
crypto_key_feature_workspace_apps_api_key: CryptoKeyFeatureWorkspaceAppsAPIKey
crypto_key_feature_oidc_convert: CryptoKeyFeatureOIDCConvert
stale_interval_ms: StaleIntervalMS
+ app_cors_behavior: AppCORSBehavior
+ cors_behavior: CORSBehavior
rules:
- name: do-not-use-public-schema-in-queries
message: "do not use public schema in queries"
diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go
index 9362d2f3e5a85..28f3e13acb7be 100644
--- a/coderd/provisionerdserver/provisionerdserver.go
+++ b/coderd/provisionerdserver/provisionerdserver.go
@@ -2225,6 +2225,14 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
openIn = database.WorkspaceAppOpenInSlimWindow
}
+ var corsBehavior database.AppCORSBehavior
+ switch app.CorsBehavior {
+ case sdkproto.AppCORSBehavior_PASSTHRU:
+ corsBehavior = database.AppCorsBehaviorPassthru
+ default:
+ corsBehavior = database.AppCorsBehaviorSimple
+ }
+
dbApp, err := db.InsertWorkspaceApp(ctx, database.InsertWorkspaceAppParams{
ID: uuid.New(),
CreatedAt: dbtime.Now(),
@@ -2251,6 +2259,7 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
DisplayOrder: int32(app.Order),
Hidden: app.Hidden,
OpenIn: openIn,
+ CORSBehavior: corsBehavior,
})
if err != nil {
return xerrors.Errorf("insert app: %w", err)
diff --git a/coderd/workspaceapps/apptest/apptest.go b/coderd/workspaceapps/apptest/apptest.go
index 4e48e60d2d47f..4e77d6cb1d7d3 100644
--- a/coderd/workspaceapps/apptest/apptest.go
+++ b/coderd/workspaceapps/apptest/apptest.go
@@ -473,6 +473,400 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
})
})
+ t.Run("WorkspaceApplicationCORS", func(t *testing.T) {
+ t.Parallel()
+
+ const external = "https://example.com"
+
+ unauthenticatedClient := func(t *testing.T, appDetails *Details) *codersdk.Client {
+ c := appDetails.AppClient(t)
+ c.SetSessionToken("")
+ return c
+ }
+
+ authenticatedClient := func(t *testing.T, appDetails *Details) *codersdk.Client {
+ uc, _ := coderdtest.CreateAnotherUser(t, appDetails.SDKClient, appDetails.FirstUser.OrganizationID, rbac.RoleMember())
+ c := appDetails.AppClient(t)
+ c.SetSessionToken(uc.SessionToken())
+ return c
+ }
+
+ ownSubdomain := func(details *Details, app App) string {
+ url := details.SubdomainAppURL(app)
+ return url.Scheme + "://" + url.Host
+ }
+
+ externalOrigin := func(*Details, App) string {
+ return external
+ }
+
+ tests := []struct {
+ name string
+ app func(details *Details) App
+ client func(t *testing.T, appDetails *Details) *codersdk.Client
+ behavior codersdk.AppCORSBehavior
+ httpMethod string
+ origin func(details *Details, app App) string
+ expectedStatusCode int
+ checkRequestHeaders func(t *testing.T, origin string, req http.Header)
+ checkResponseHeaders func(t *testing.T, origin string, resp http.Header)
+ }{
+ // Public
+ {
+ // The default behavior is to accept preflight requests from the request origin if it matches the app's own subdomain.
+ name: "Default/Public/Preflight/Subdomain",
+ app: func(details *Details) App { return details.Apps.PublicCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: unauthenticatedClient,
+ httpMethod: http.MethodOptions,
+ origin: ownSubdomain,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Contains(t, resp.Get("Access-Control-Allow-Methods"), http.MethodGet)
+ assert.Equal(t, "true", resp.Get("Access-Control-Allow-Credentials"))
+ },
+ },
+ {
+ // The default behavior is to reject preflight requests from origins other than the app's own subdomain.
+ name: "Default/Public/Preflight/External",
+ app: func(details *Details) App { return details.Apps.PublicCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: unauthenticatedClient,
+ httpMethod: http.MethodOptions,
+ origin: externalOrigin,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ // We don't add a valid Allow-Origin header for requests we won't proxy.
+ assert.Empty(t, resp.Get("Access-Control-Allow-Origin"))
+ },
+ },
+ {
+ // A request without an Origin header would be rejected by an actual browser since it lacks CORS headers.
+ name: "Default/Public/GET/NoOrigin",
+ app: func(details *Details) App { return details.Apps.PublicCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: unauthenticatedClient,
+ origin: func(*Details, App) string { return "" },
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Empty(t, resp.Get("Access-Control-Allow-Origin"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Headers"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Credentials"))
+ // Added by the app handler.
+ assert.Equal(t, "simple", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // The passthru behavior will pass through the request headers to the upstream app.
+ name: "Passthru/Public/Preflight/Subdomain",
+ app: func(details *Details) App { return details.Apps.PublicCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkRequestHeaders: func(t *testing.T, origin string, req http.Header) {
+ assert.Equal(t, origin, req.Get("Origin"))
+ assert.Equal(t, "GET", req.Get("Access-Control-Request-Method"))
+ },
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // Identical to the previous test, but the origin is different.
+ name: "Passthru/Public/PreflightOther",
+ app: func(details *Details) App { return details.Apps.PublicCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkRequestHeaders: func(t *testing.T, origin string, req http.Header) {
+ assert.Equal(t, origin, req.Get("Origin"))
+ assert.Equal(t, "GET", req.Get("Access-Control-Request-Method"))
+ assert.Equal(t, "X-Got-Host", req.Get("Access-Control-Request-Headers"))
+ },
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // A request without an Origin header would be rejected by an actual browser since it lacks CORS headers.
+ name: "Passthru/Public/GET/NoOrigin",
+ app: func(details *Details) App { return details.Apps.PublicCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: func(*Details, App) string { return "" },
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Empty(t, resp.Get("Access-Control-Allow-Origin"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Headers"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Credentials"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ // Authenticated
+ {
+ // Same behavior as Default/Public/Preflight/Subdomain.
+ name: "Default/Authenticated/Preflight/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: authenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Contains(t, resp.Get("Access-Control-Allow-Methods"), http.MethodGet)
+ assert.Equal(t, "true", resp.Get("Access-Control-Allow-Credentials"))
+ assert.Equal(t, "X-Got-Host", resp.Get("Access-Control-Allow-Headers"))
+ },
+ },
+ {
+ // Same behavior as Default/Public/Preflight/External.
+ name: "Default/Authenticated/Preflight/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: authenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Empty(t, resp.Get("Access-Control-Allow-Origin"))
+ },
+ },
+ {
+ // An authenticated request to the app is allowed from its own subdomain.
+ name: "Default/Authenticated/GET/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: authenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, "true", resp.Get("Access-Control-Allow-Credentials"))
+ // Added by the app handler.
+ assert.Equal(t, "simple", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // An authenticated request to the app is allowed from an external origin.
+ // The origin doesn't match the app's own subdomain, so the CORS headers are not added.
+ name: "Default/Authenticated/GET/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSDefault },
+ behavior: codersdk.AppCORSBehaviorSimple,
+ client: authenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Empty(t, resp.Get("Access-Control-Allow-Origin"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Headers"))
+ assert.Empty(t, resp.Get("Access-Control-Allow-Credentials"))
+ // Added by the app handler.
+ assert.Equal(t, "simple", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // The request is rejected because the client is unauthenticated.
+ name: "Passthru/Unauthenticated/Preflight/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusSeeOther,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.NotEmpty(t, resp.Get("Location"))
+ },
+ },
+ {
+ // Same behavior as the above test, but the origin is different.
+ name: "Passthru/Unauthenticated/Preflight/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusSeeOther,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.NotEmpty(t, resp.Get("Location"))
+ },
+ },
+ {
+ // The request is rejected because the client is unauthenticated.
+ name: "Passthru/Unauthenticated/GET/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusSeeOther,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.NotEmpty(t, resp.Get("Location"))
+ },
+ },
+ {
+ // Same behavior as the above test, but the origin is different.
+ name: "Passthru/Unauthenticated/GET/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: unauthenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusSeeOther,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.NotEmpty(t, resp.Get("Location"))
+ },
+ },
+ {
+ // The request is allowed because the client is authenticated.
+ name: "Passthru/Authenticated/Preflight/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: authenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // Same behavior as the above test, but the origin is different.
+ name: "Passthru/Authenticated/Preflight/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: authenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodOptions,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // The request is allowed because the client is authenticated.
+ name: "Passthru/Authenticated/GET/Subdomain",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: authenticatedClient,
+ origin: ownSubdomain,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ {
+ // Same behavior as the above test, but the origin is different.
+ name: "Passthru/Authenticated/GET/External",
+ app: func(details *Details) App { return details.Apps.AuthenticatedCORSPassthru },
+ behavior: codersdk.AppCORSBehaviorPassthru,
+ client: authenticatedClient,
+ origin: externalOrigin,
+ httpMethod: http.MethodGet,
+ expectedStatusCode: http.StatusOK,
+ checkResponseHeaders: func(t *testing.T, origin string, resp http.Header) {
+ assert.Equal(t, origin, resp.Get("Access-Control-Allow-Origin"))
+ assert.Equal(t, http.MethodGet, resp.Get("Access-Control-Allow-Methods"))
+ // Added by the app handler.
+ assert.Equal(t, "passthru", resp.Get("X-CORS-Handler"))
+ },
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ ctx := testutil.Context(t, testutil.WaitLong)
+
+ var reqHeaders http.Header
+ // Setup an HTTP handler which is the "app"; this handler conditionally responds
+ // to requests based on the CORS behavior
+ appDetails := setupProxyTest(t, &DeploymentOptions{
+ handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ _, err := r.Cookie(codersdk.SessionTokenCookie)
+ assert.ErrorIs(t, err, http.ErrNoCookie)
+
+ // Store the request headers for later assertions
+ reqHeaders = r.Header
+
+ switch tc.behavior {
+ case codersdk.AppCORSBehaviorPassthru:
+ w.Header().Set("X-CORS-Handler", "passthru")
+
+ // Only allow GET and OPTIONS requests
+ if r.Method != http.MethodGet && r.Method != http.MethodOptions {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ // If the Origin header is present, add the CORS headers.
+ if origin := r.Header.Get("Origin"); origin != "" {
+ w.Header().Set("Access-Control-Allow-Credentials", "true")
+ w.Header().Set("Access-Control-Allow-Origin", origin)
+ w.Header().Set("Access-Control-Allow-Methods", http.MethodGet)
+ }
+
+ w.WriteHeader(http.StatusOK)
+ case codersdk.AppCORSBehaviorSimple:
+ w.Header().Set("X-CORS-Handler", "simple")
+ }
+ }),
+ })
+
+ // Given: a client and a workspace app
+ client := tc.client(t, appDetails)
+ path := appDetails.SubdomainAppURL(tc.app(appDetails)).String()
+ origin := tc.origin(appDetails, tc.app(appDetails))
+
+ // When: a preflight request is made to an app with a specified CORS behavior
+ resp, err := requestWithRetries(ctx, t, client, tc.httpMethod, path, nil, func(r *http.Request) {
+ // Mimic non-browser clients that don't send the Origin header.
+ if origin != "" {
+ r.Header.Set("Origin", origin)
+ }
+ r.Header.Set("Access-Control-Request-Method", "GET")
+ r.Header.Set("Access-Control-Request-Headers", "X-Got-Host")
+ })
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ // Then: the request & response must match expectations
+ assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
+ assert.NoError(t, err)
+ if tc.checkRequestHeaders != nil {
+ tc.checkRequestHeaders(t, origin, reqHeaders)
+ }
+ tc.checkResponseHeaders(t, origin, resp.Header)
+ })
+ }
+ })
+
t.Run("WorkspaceApplicationAuth", func(t *testing.T) {
t.Parallel()
@@ -1389,7 +1783,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
forceURLTransport(t, client)
// Create workspace.
- port := appServer(t, nil, false)
+ port := appServer(t, nil, false, nil)
workspace, _ = createWorkspaceWithApps(t, client, user.OrganizationIDs[0], user, port, false)
// Verify that the apps have the correct sharing levels set.
@@ -1400,10 +1794,14 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
agnt = workspaceBuild.Resources[0].Agents[0]
found := map[string]codersdk.WorkspaceAppSharingLevel{}
expected := map[string]codersdk.WorkspaceAppSharingLevel{
- proxyTestAppNameFake: codersdk.WorkspaceAppSharingLevelOwner,
- proxyTestAppNameOwner: codersdk.WorkspaceAppSharingLevelOwner,
- proxyTestAppNameAuthenticated: codersdk.WorkspaceAppSharingLevelAuthenticated,
- proxyTestAppNamePublic: codersdk.WorkspaceAppSharingLevelPublic,
+ proxyTestAppNameFake: codersdk.WorkspaceAppSharingLevelOwner,
+ proxyTestAppNameOwner: codersdk.WorkspaceAppSharingLevelOwner,
+ proxyTestAppNameAuthenticated: codersdk.WorkspaceAppSharingLevelAuthenticated,
+ proxyTestAppNamePublic: codersdk.WorkspaceAppSharingLevelPublic,
+ proxyTestAppNameAuthenticatedCORSPassthru: codersdk.WorkspaceAppSharingLevelAuthenticated,
+ proxyTestAppNamePublicCORSPassthru: codersdk.WorkspaceAppSharingLevelPublic,
+ proxyTestAppNameAuthenticatedCORSDefault: codersdk.WorkspaceAppSharingLevelAuthenticated,
+ proxyTestAppNamePublicCORSDefault: codersdk.WorkspaceAppSharingLevelPublic,
}
for _, app := range agnt.Apps {
found[app.DisplayName] = app.SharingLevel
@@ -1560,6 +1958,12 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
// Unauthenticated user should not have any access.
verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNameAuthenticated, clientWithNoAuth, false, true)
+
+ // Unauthenticated user should not have any access, regardless of CORS behavior (using passthru).
+ verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNameAuthenticatedCORSPassthru, clientWithNoAuth, false, true)
+
+ // Unauthenticated user should not have any access, regardless of CORS behavior (using default).
+ verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNameAuthenticatedCORSDefault, clientWithNoAuth, false, true)
})
t.Run("LevelPublic", func(t *testing.T) {
@@ -1577,6 +1981,12 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
// Unauthenticated user should be able to access the workspace.
verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNamePublic, clientWithNoAuth, allowedUnlessSharingDisabled, !allowedUnlessSharingDisabled)
+
+ // Unauthenticated user should have access, regardless of CORS behavior (using passthru).
+ verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNamePublicCORSPassthru, clientWithNoAuth, allowedUnlessSharingDisabled, !allowedUnlessSharingDisabled)
+
+ // Unauthenticated user should have access, regardless of CORS behavior (using default).
+ verifyAccess(t, appDetails, isPathApp, user.Username, workspace.Name, agnt.Name, proxyTestAppNamePublicCORSDefault, clientWithNoAuth, allowedUnlessSharingDisabled, !allowedUnlessSharingDisabled)
})
}
@@ -1780,6 +2190,86 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
require.Equal(t, []string{"baz"}, resp.Header.Values("X-Foobar"))
})
+ // See above test for original implementation.
+ t.Run("CORSHeadersConditionallyStripped", func(t *testing.T) {
+ t.Parallel()
+
+ // Set a bunch of headers which may or may not be stripped, depending on the CORS behavior.
+ // See coderd/workspaceapps/proxy.go (proxyWorkspaceApp).
+ headers := http.Header{
+ "X-Foobar": []string{"baz"},
+ "Access-Control-Allow-Origin": []string{"http://localhost"},
+ "access-control-allow-origin": []string{"http://localhost"},
+ "Access-Control-Allow-Credentials": []string{"true"},
+ "Access-Control-Allow-Methods": []string{"PUT"},
+ "Access-Control-Allow-Headers": []string{"X-Foobar"},
+ }
+
+ appDetails := setupProxyTest(t, &DeploymentOptions{
+ headers: headers,
+ })
+
+ tests := []struct {
+ name string
+ app App
+ shouldStrip bool
+ }{
+ {
+ // Uses an app which does not set CORS behavior, which *should* be equivalent to default.
+ name: "NormalStrip",
+ app: appDetails.Apps.Owner,
+ shouldStrip: true,
+ },
+ {
+ // Explicitly uses the default CORS behavior.
+ name: "DefaultStrip",
+ app: appDetails.Apps.PublicCORSDefault,
+ shouldStrip: true,
+ },
+ {
+ // Explicitly does not strip CORS headers.
+ name: "PassthruNoStrip",
+ app: appDetails.Apps.PublicCORSPassthru,
+ shouldStrip: false,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ ctx := testutil.Context(t, testutil.WaitLong)
+
+ // Given: a particular app
+ appURL := appDetails.SubdomainAppURL(tc.app)
+
+ // When: querying the app
+ resp, err := requestWithRetries(ctx, t, appDetails.AppClient(t), http.MethodGet, appURL.String(), nil)
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ require.Equal(t, http.StatusOK, resp.StatusCode)
+
+ // Then: the CORS headers should be conditionally stripped or not, depending on the CORS behavior.
+ if tc.shouldStrip {
+ require.Empty(t, resp.Header.Values("Access-Control-Allow-Origin"))
+ require.Empty(t, resp.Header.Values("Access-Control-Allow-Credentials"))
+ require.Empty(t, resp.Header.Values("Access-Control-Allow-Methods"))
+ require.Empty(t, resp.Header.Values("Access-Control-Allow-Headers"))
+ } else {
+ for k, v := range headers {
+ // We dedupe the values because some headers have been set multiple times.
+ headerVal := dedupe(resp.Header.Values(k))
+ assert.ElementsMatchf(t, headerVal, v, "header %q does not contain %q", k, v)
+ }
+ }
+
+ // This header is not a CORS-related header, so it should always be set.
+ require.Equal(t, []string{"baz"}, resp.Header.Values("X-Foobar"))
+ })
+ }
+ })
+
t.Run("ReportStats", func(t *testing.T) {
t.Parallel()
@@ -2001,3 +2491,16 @@ func findCookie(cookies []*http.Cookie, name string) *http.Cookie {
}
return nil
}
+
+func dedupe[T comparable](elements []T) []T {
+ found := map[T]bool{}
+ result := []T{}
+
+ for _, v := range elements {
+ if !found[v] {
+ found[v] = true
+ result = append(result, v)
+ }
+ }
+ return result
+}
diff --git a/coderd/workspaceapps/apptest/setup.go b/coderd/workspaceapps/apptest/setup.go
index 9d1df9e7fe09d..98db937017853 100644
--- a/coderd/workspaceapps/apptest/setup.go
+++ b/coderd/workspaceapps/apptest/setup.go
@@ -36,8 +36,13 @@ const (
proxyTestAppNameOwner = "test-app-owner"
proxyTestAppNameAuthenticated = "test-app-authenticated"
proxyTestAppNamePublic = "test-app-public"
- proxyTestAppQuery = "query=true"
- proxyTestAppBody = "hello world from apps test"
+ // nolint:gosec // Not a secret
+ proxyTestAppNameAuthenticatedCORSPassthru = "test-app-authenticated-cors-passthru"
+ proxyTestAppNamePublicCORSPassthru = "test-app-public-cors-passthru"
+ proxyTestAppNameAuthenticatedCORSDefault = "test-app-authenticated-cors-default"
+ proxyTestAppNamePublicCORSDefault = "test-app-public-cors-default"
+ proxyTestAppQuery = "query=true"
+ proxyTestAppBody = "hello world from apps test"
proxyTestSubdomainRaw = "*.test.coder.com"
proxyTestSubdomain = "test.coder.com"
@@ -60,6 +65,7 @@ type DeploymentOptions struct {
noWorkspace bool
port uint16
headers http.Header
+ handler http.Handler
}
// Deployment is a license-agnostic deployment with all the fields that apps
@@ -93,6 +99,10 @@ type App struct {
// Prefix should have ---.
Prefix string
Query string
+ Path string
+
+ // Control the behavior of CORS handling.
+ CORSBehavior codersdk.AppCORSBehavior
}
// Details are the full test details returned from setupProxyTestWithFactory.
@@ -109,12 +119,16 @@ type Details struct {
AppPort uint16
Apps struct {
- Fake App
- Owner App
- Authenticated App
- Public App
- Port App
- PortHTTPS App
+ Fake App
+ Owner App
+ Authenticated App
+ Public App
+ Port App
+ PortHTTPS App
+ PublicCORSPassthru App
+ AuthenticatedCORSPassthru App
+ PublicCORSDefault App
+ AuthenticatedCORSDefault App
}
}
@@ -201,7 +215,7 @@ func setupProxyTestWithFactory(t *testing.T, factory DeploymentFactory, opts *De
}
if opts.port == 0 {
- opts.port = appServer(t, opts.headers, opts.ServeHTTPS)
+ opts.port = appServer(t, opts.headers, opts.ServeHTTPS, opts.handler)
}
workspace, agnt := createWorkspaceWithApps(t, deployment.SDKClient, deployment.FirstUser.OrganizationID, me, opts.port, opts.ServeHTTPS)
@@ -252,30 +266,64 @@ func setupProxyTestWithFactory(t *testing.T, factory DeploymentFactory, opts *De
AgentName: agnt.Name,
AppSlugOrPort: strconv.Itoa(int(opts.port)) + "s",
}
+ details.Apps.PublicCORSPassthru = App{
+ Username: me.Username,
+ WorkspaceName: workspace.Name,
+ AgentName: agnt.Name,
+ AppSlugOrPort: proxyTestAppNamePublicCORSPassthru,
+ CORSBehavior: codersdk.AppCORSBehaviorPassthru,
+ Query: proxyTestAppQuery,
+ }
+ details.Apps.AuthenticatedCORSPassthru = App{
+ Username: me.Username,
+ WorkspaceName: workspace.Name,
+ AgentName: agnt.Name,
+ AppSlugOrPort: proxyTestAppNameAuthenticatedCORSPassthru,
+ CORSBehavior: codersdk.AppCORSBehaviorPassthru,
+ Query: proxyTestAppQuery,
+ }
+ details.Apps.PublicCORSDefault = App{
+ Username: me.Username,
+ WorkspaceName: workspace.Name,
+ AgentName: agnt.Name,
+ AppSlugOrPort: proxyTestAppNamePublicCORSDefault,
+ Query: proxyTestAppQuery,
+ }
+ details.Apps.AuthenticatedCORSDefault = App{
+ Username: me.Username,
+ WorkspaceName: workspace.Name,
+ AgentName: agnt.Name,
+ AppSlugOrPort: proxyTestAppNameAuthenticatedCORSDefault,
+ Query: proxyTestAppQuery,
+ }
return details
}
//nolint:revive
-func appServer(t *testing.T, headers http.Header, isHTTPS bool) uint16 {
- server := httptest.NewUnstartedServer(
- http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- _, err := r.Cookie(codersdk.SessionTokenCookie)
- assert.ErrorIs(t, err, http.ErrNoCookie)
- w.Header().Set("X-Forwarded-For", r.Header.Get("X-Forwarded-For"))
- w.Header().Set("X-Got-Host", r.Host)
- for name, values := range headers {
- for _, value := range values {
- w.Header().Add(name, value)
- }
+func appServer(t *testing.T, headers http.Header, isHTTPS bool, handler http.Handler) uint16 {
+ defaultHandler := http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ _, err := r.Cookie(codersdk.SessionTokenCookie)
+ assert.ErrorIs(t, err, http.ErrNoCookie)
+ w.Header().Set("X-Forwarded-For", r.Header.Get("X-Forwarded-For"))
+ w.Header().Set("X-Got-Host", r.Host)
+ for name, values := range headers {
+ for _, value := range values {
+ w.Header().Add(name, value)
}
- w.WriteHeader(http.StatusOK)
- _, _ = w.Write([]byte(proxyTestAppBody))
- },
- ),
+ }
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(proxyTestAppBody))
+ },
)
+ if handler == nil {
+ handler = defaultHandler
+ }
+
+ server := httptest.NewUnstartedServer(handler)
+
server.Config.ReadHeaderTimeout = time.Minute
if isHTTPS {
server.StartTLS()
@@ -361,6 +409,36 @@ func createWorkspaceWithApps(t *testing.T, client *codersdk.Client, orgID uuid.U
Url: appURL,
Subdomain: true,
},
+ {
+ Slug: proxyTestAppNamePublicCORSPassthru,
+ DisplayName: proxyTestAppNamePublicCORSPassthru,
+ SharingLevel: proto.AppSharingLevel_PUBLIC,
+ Url: appURL,
+ Subdomain: true,
+ CorsBehavior: proto.AppCORSBehavior_PASSTHRU,
+ },
+ {
+ Slug: proxyTestAppNameAuthenticatedCORSPassthru,
+ DisplayName: proxyTestAppNameAuthenticatedCORSPassthru,
+ SharingLevel: proto.AppSharingLevel_AUTHENTICATED,
+ Url: appURL,
+ Subdomain: true,
+ CorsBehavior: proto.AppCORSBehavior_PASSTHRU,
+ },
+ {
+ Slug: proxyTestAppNamePublicCORSDefault,
+ DisplayName: proxyTestAppNamePublicCORSDefault,
+ SharingLevel: proto.AppSharingLevel_PUBLIC,
+ Url: appURL,
+ Subdomain: true,
+ },
+ {
+ Slug: proxyTestAppNameAuthenticatedCORSDefault,
+ DisplayName: proxyTestAppNameAuthenticatedCORSDefault,
+ SharingLevel: proto.AppSharingLevel_AUTHENTICATED,
+ Url: appURL,
+ Subdomain: true,
+ },
}
version := coderdtest.CreateTemplateVersion(t, client, orgID, &echo.Responses{
Parse: echo.ParseComplete,
diff --git a/coderd/workspaceapps/cors/cors.go b/coderd/workspaceapps/cors/cors.go
new file mode 100644
index 0000000000000..c204cb322f173
--- /dev/null
+++ b/coderd/workspaceapps/cors/cors.go
@@ -0,0 +1,21 @@
+package cors
+
+import (
+ "context"
+
+ "github.com/coder/coder/v2/codersdk"
+)
+
+type contextKeyBehavior struct{}
+
+// WithBehavior sets the CORS behavior for the given context.
+func WithBehavior(ctx context.Context, behavior codersdk.AppCORSBehavior) context.Context {
+ return context.WithValue(ctx, contextKeyBehavior{}, behavior)
+}
+
+// HasBehavior returns true if the given context has the specified CORS behavior.
+func HasBehavior(ctx context.Context, behavior codersdk.AppCORSBehavior) bool {
+ val := ctx.Value(contextKeyBehavior{})
+ b, ok := val.(codersdk.AppCORSBehavior)
+ return ok && b == behavior
+}
diff --git a/coderd/workspaceapps/db.go b/coderd/workspaceapps/db.go
index 90c6f107daa5e..9234e304c1162 100644
--- a/coderd/workspaceapps/db.go
+++ b/coderd/workspaceapps/db.go
@@ -152,6 +152,7 @@ func (p *DBTokenProvider) Issue(ctx context.Context, rw http.ResponseWriter, r *
if dbReq.AppURL != nil {
token.AppURL = dbReq.AppURL.String()
}
+ token.CORSBehavior = codersdk.AppCORSBehavior(dbReq.AppCORSBehavior)
// Verify the user has access to the app.
authed, warnings, err := p.authorizeRequest(r.Context(), authz, dbReq)
diff --git a/coderd/workspaceapps/db_test.go b/coderd/workspaceapps/db_test.go
index 597d1daadfa54..720685ae9a922 100644
--- a/coderd/workspaceapps/db_test.go
+++ b/coderd/workspaceapps/db_test.go
@@ -320,11 +320,12 @@ func Test_ResolveRequest(t *testing.T) {
RegisteredClaims: jwtutils.RegisteredClaims{
Expiry: jwt.NewNumericDate(token.Expiry.Time()),
},
- Request: req,
- UserID: me.ID,
- WorkspaceID: workspace.ID,
- AgentID: agentID,
- AppURL: appURL,
+ Request: req,
+ UserID: me.ID,
+ WorkspaceID: workspace.ID,
+ AgentID: agentID,
+ AppURL: appURL,
+ CORSBehavior: token.CORSBehavior,
}, token)
require.NotZero(t, token.Expiry)
require.WithinDuration(t, time.Now().Add(workspaceapps.DefaultTokenExpiry), token.Expiry.Time(), time.Minute)
diff --git a/coderd/workspaceapps/provider.go b/coderd/workspaceapps/provider.go
index 1cd652976f6f4..aa2515ffb4605 100644
--- a/coderd/workspaceapps/provider.go
+++ b/coderd/workspaceapps/provider.go
@@ -7,6 +7,7 @@ import (
"time"
"cdr.dev/slog"
+
"github.com/coder/coder/v2/codersdk"
)
diff --git a/coderd/workspaceapps/proxy.go b/coderd/workspaceapps/proxy.go
index bc8d32ed2ead9..907803679b713 100644
--- a/coderd/workspaceapps/proxy.go
+++ b/coderd/workspaceapps/proxy.go
@@ -28,6 +28,7 @@ import (
"github.com/coder/coder/v2/coderd/tracing"
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
+ "github.com/coder/coder/v2/coderd/workspaceapps/cors"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/coder/v2/site"
@@ -394,36 +395,38 @@ func (s *Server) HandleSubdomain(middlewares ...func(http.Handler) http.Handler)
return
}
+ // Cookie smuggling needs to happen before CORs behavior is determined.
+ if !s.handleAPIKeySmuggling(rw, r, AccessMethodSubdomain) {
+ return
+ }
+
+ token, ok := ResolveRequest(rw, r, ResolveRequestOptions{
+ Logger: s.Logger,
+ CookieCfg: s.Cookies,
+ SignedTokenProvider: s.SignedTokenProvider,
+ DashboardURL: s.DashboardURL,
+ PathAppBaseURL: s.AccessURL,
+ AppHostname: s.Hostname,
+ AppRequest: Request{
+ AccessMethod: AccessMethodSubdomain,
+ BasePath: "/",
+ Prefix: app.Prefix,
+ UsernameOrID: app.Username,
+ WorkspaceNameOrID: app.WorkspaceName,
+ AgentNameOrID: app.AgentName,
+ AppSlugOrPort: app.AppSlugOrPort,
+ },
+ AppPath: r.URL.Path,
+ AppQuery: r.URL.RawQuery,
+ })
+ if !ok {
+ return
+ }
+
// Use the passed in app middlewares before checking authentication and
// passing to the proxy app.
- mws := chi.Middlewares(append(middlewares, httpmw.WorkspaceAppCors(s.HostnameRegex, app)))
+ mws := chi.Middlewares(append(middlewares, s.determineCORSBehavior(token, app)))
mws.Handler(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if !s.handleAPIKeySmuggling(rw, r, AccessMethodSubdomain) {
- return
- }
-
- token, ok := ResolveRequest(rw, r, ResolveRequestOptions{
- Logger: s.Logger,
- CookieCfg: s.Cookies,
- SignedTokenProvider: s.SignedTokenProvider,
- DashboardURL: s.DashboardURL,
- PathAppBaseURL: s.AccessURL,
- AppHostname: s.Hostname,
- AppRequest: Request{
- AccessMethod: AccessMethodSubdomain,
- BasePath: "/",
- Prefix: app.Prefix,
- UsernameOrID: app.Username,
- WorkspaceNameOrID: app.WorkspaceName,
- AgentNameOrID: app.AgentName,
- AppSlugOrPort: app.AppSlugOrPort,
- },
- AppPath: r.URL.Path,
- AppQuery: r.URL.RawQuery,
- })
- if !ok {
- return
- }
s.proxyWorkspaceApp(rw, r, *token, r.URL.Path, app)
})).ServeHTTP(rw, r.WithContext(ctx))
})
@@ -560,6 +563,11 @@ func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appT
proxy := s.AgentProvider.ReverseProxy(appURL, s.DashboardURL, appToken.AgentID, app, s.Hostname)
proxy.ModifyResponse = func(r *http.Response) error {
+ // If passthru behavior is set, disable our CORS header stripping.
+ if cors.HasBehavior(r.Request.Context(), codersdk.AppCORSBehaviorPassthru) {
+ return nil
+ }
+
r.Header.Del(httpmw.AccessControlAllowOriginHeader)
r.Header.Del(httpmw.AccessControlAllowCredentialsHeader)
r.Header.Del(httpmw.AccessControlAllowMethodsHeader)
@@ -765,3 +773,34 @@ func WebsocketNetConn(ctx context.Context, conn *websocket.Conn, msgType websock
Conn: nc,
}
}
+
+// determineCORSBehavior examines the given token and conditionally applies
+// CORS middleware if the token specifies that behavior.
+func (s *Server) determineCORSBehavior(token *SignedToken, app appurl.ApplicationURL) func(http.Handler) http.Handler {
+ return func(next http.Handler) http.Handler {
+ // Create the CORS middleware handler upfront.
+ corsHandler := httpmw.WorkspaceAppCors(s.HostnameRegex, app)(next)
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ var behavior codersdk.AppCORSBehavior
+ if token != nil {
+ behavior = token.CORSBehavior
+ }
+
+ // Add behavior to context regardless of which handler we use,
+ // since we will use this later on to determine if we should strip
+ // CORS headers in the response.
+ r = r.WithContext(cors.WithBehavior(r.Context(), behavior))
+
+ switch behavior {
+ case codersdk.AppCORSBehaviorPassthru:
+ // Bypass the CORS middleware.
+ next.ServeHTTP(rw, r)
+ return
+ default:
+ // Apply the CORS middleware.
+ corsHandler.ServeHTTP(rw, r)
+ }
+ })
+ }
+}
diff --git a/coderd/workspaceapps/request.go b/coderd/workspaceapps/request.go
index 0e6a43cb4cbe4..aabca1a648f0b 100644
--- a/coderd/workspaceapps/request.go
+++ b/coderd/workspaceapps/request.go
@@ -204,6 +204,8 @@ type databaseRequest struct {
// AppSharingLevel is the sharing level of the app. This is forced to be set
// to AppSharingLevelOwner if the access method is terminal.
AppSharingLevel database.AppSharingLevel
+ // AppCORSBehavior defines the behavior of the CORS middleware.
+ AppCORSBehavior database.AppCORSBehavior
}
// getDatabase does queries to get the owner user, workspace and agent
@@ -293,12 +295,16 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
app database.WorkspaceApp
appURL string
appSharingLevel database.AppSharingLevel
+ appCORSBehavior database.AppCORSBehavior
// First check if it's a port-based URL with an optional "s" suffix for HTTPS.
potentialPortStr = strings.TrimSuffix(r.AppSlugOrPort, "s")
portUint, portUintErr = strconv.ParseUint(potentialPortStr, 10, 16)
)
//nolint:nestif
if portUintErr == nil {
+ // TODO: handle CORS passthru for port sharing use-case.
+ appCORSBehavior = database.AppCorsBehaviorSimple
+
protocol := "http"
if strings.HasSuffix(r.AppSlugOrPort, "s") {
protocol = "https"
@@ -370,6 +376,7 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
appSharingLevel = database.AppSharingLevelOwner
}
appURL = app.Url.String
+ appCORSBehavior = app.CORSBehavior
break
}
}
@@ -417,6 +424,7 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
App: app,
AppURL: appURLParsed,
AppSharingLevel: appSharingLevel,
+ AppCORSBehavior: appCORSBehavior,
}, nil
}
diff --git a/coderd/workspaceapps/token.go b/coderd/workspaceapps/token.go
index dcd8c5a0e5c34..d46f7b9335212 100644
--- a/coderd/workspaceapps/token.go
+++ b/coderd/workspaceapps/token.go
@@ -22,10 +22,11 @@ type SignedToken struct {
// Request details.
Request `json:"request"`
- UserID uuid.UUID `json:"user_id"`
- WorkspaceID uuid.UUID `json:"workspace_id"`
- AgentID uuid.UUID `json:"agent_id"`
- AppURL string `json:"app_url"`
+ UserID uuid.UUID `json:"user_id"`
+ WorkspaceID uuid.UUID `json:"workspace_id"`
+ AgentID uuid.UUID `json:"agent_id"`
+ AppURL string `json:"app_url"`
+ CORSBehavior codersdk.AppCORSBehavior `json:"cors_behavior"`
}
// MatchesRequest returns true if the token matches the request. Any token that
diff --git a/codersdk/cors_behavior.go b/codersdk/cors_behavior.go
new file mode 100644
index 0000000000000..8fd8b9a893e37
--- /dev/null
+++ b/codersdk/cors_behavior.go
@@ -0,0 +1,17 @@
+package codersdk
+
+import "golang.org/x/xerrors"
+
+type AppCORSBehavior string
+
+const (
+ AppCORSBehaviorSimple AppCORSBehavior = "simple"
+ AppCORSBehaviorPassthru AppCORSBehavior = "passthru"
+)
+
+func (c AppCORSBehavior) Validate() error {
+ if c != AppCORSBehaviorSimple && c != AppCORSBehaviorPassthru {
+ return xerrors.New("Invalid CORS behavior.")
+ }
+ return nil
+}
diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md
index c9124efa14bf0..f0fdc1ab68461 100644
--- a/docs/admin/security/audit-logs.md
+++ b/docs/admin/security/audit-logs.md
@@ -30,7 +30,7 @@ We track the following resources:
| TemplateVersioncreate, write |
Field Tracked | archived true created_at false created_by true created_by_avatar_url false created_by_username false external_auth_providers false id true job_id false message false name true organization_id false readme true source_example_id false template_id true updated_at false
|
| Usercreate, write, delete | Field Tracked | avatar_url false created_at false deleted true email true github_com_user_id false hashed_one_time_passcode false hashed_password true id true is_system true last_seen_at false login_type true name true one_time_passcode_expires_at true quiet_hours_schedule true rbac_roles true status true updated_at false username true
|
| WorkspaceAgentconnect, disconnect | Field Tracked | api_version false architecture false auth_instance_id false auth_token false connection_timeout_seconds false created_at false directory false disconnected_at false display_apps false display_order false environment_variables false expanded_directory false first_connected_at false id false instance_metadata false last_connected_at false last_connected_replica_id false lifecycle_state false logs_length false logs_overflowed false motd_file false name false operating_system false ready_at false resource_id false resource_metadata false started_at false subsystems false troubleshooting_url false updated_at false version false
|
-| WorkspaceAppopen, close | Field Tracked | agent_id false command false created_at false display_name false display_order false external false health false healthcheck_interval false healthcheck_threshold false healthcheck_url false hidden false icon false id false open_in false sharing_level false slug false subdomain false url false
|
+| WorkspaceAppopen, close | Field Tracked | agent_id false command false cors_behavior false created_at false display_name false display_order false external false health false healthcheck_interval false healthcheck_threshold false healthcheck_url false hidden false icon false id false open_in false sharing_level false slug false subdomain false url false
|
| WorkspaceBuildstart, stop | Field Tracked | build_number false created_at false daily_cost false deadline false id false initiator_by_avatar_url false initiator_by_username false initiator_id false job_id false max_deadline false provisioner_state false reason false template_version_id true template_version_preset_id false transition false updated_at false workspace_id false
|
| WorkspaceProxy | Field Tracked | created_at true deleted false derp_enabled true derp_only true display_name true icon true id true name true region_id true token_hashed_secret true updated_at false url true version true wildcard_hostname true
|
| WorkspaceTable | Field Tracked | automatic_updates true autostart_schedule true created_at false deleted false deleting_at true dormant_at true favorite true id true last_used_at false name true next_start_at true organization_id false owner_id true template_id true ttl true updated_at false
|
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index 84cc7d451b4f1..546824f9cd245 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -362,6 +362,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"display_order": ActionIgnore,
"hidden": ActionIgnore,
"open_in": ActionIgnore,
+ "cors_behavior": ActionIgnore,
},
}
diff --git a/enterprise/wsproxy/wsproxy.go b/enterprise/wsproxy/wsproxy.go
index bce49417fcd35..69241d8aa1c17 100644
--- a/enterprise/wsproxy/wsproxy.go
+++ b/enterprise/wsproxy/wsproxy.go
@@ -339,11 +339,11 @@ func New(ctx context.Context, opts *Options) (*Server, error) {
httpmw.ExtractRealIP(s.Options.RealIPConfig),
loggermw.Logger(s.Logger),
prometheusMW,
- corsMW,
// HandleSubdomain is a middleware that handles all requests to the
// subdomain-based workspace apps.
s.AppServer.HandleSubdomain(apiRateLimiter),
+ corsMW,
// Build-Version is helpful for debugging.
func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
diff --git a/examples/cors_demo/main.go b/examples/cors_demo/main.go
new file mode 100644
index 0000000000000..95b3e2008e649
--- /dev/null
+++ b/examples/cors_demo/main.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "html/template"
+ "log"
+ "net/http"
+)
+
+var enableCORS bool
+var port int
+
+func main() {
+ flag.IntVar(&port, "port", 7600, "Port to run the server on")
+ flag.BoolVar(&enableCORS, "cors", false, "Enable CORS headers")
+ flag.Parse()
+
+ http.HandleFunc("/", serveHTML)
+ http.HandleFunc("/test", testHandler)
+
+ fmt.Printf("Server started at :%d\n", port)
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
+}
+
+func serveHTML(w http.ResponseWriter, r *http.Request) {
+ if enableCORS {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ }
+ tmpl := `
+
+
+
+ Fetch Test
+
+
+ Fetch Tester
+
+
+ GET
+ POST
+ PUT
+ DELETE
+
+ Send Request
+
+
+
+
+
+ `
+ t := template.Must(template.New("page").Parse(tmpl))
+ t.Execute(w, nil)
+}
+
+func testHandler(w http.ResponseWriter, r *http.Request) {
+ if enableCORS {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ }
+ fmt.Fprintf(w, "You made a %s request to /test", r.Method)
+}
diff --git a/provisioner/terraform/resources.go b/provisioner/terraform/resources.go
index da86ab2f3d48e..264e278d60ae7 100644
--- a/provisioner/terraform/resources.go
+++ b/provisioner/terraform/resources.go
@@ -98,17 +98,18 @@ type agentAppAttributes struct {
Slug string `mapstructure:"slug"`
DisplayName string `mapstructure:"display_name"`
// Name is deprecated in favor of DisplayName.
- Name string `mapstructure:"name"`
- Icon string `mapstructure:"icon"`
- URL string `mapstructure:"url"`
- External bool `mapstructure:"external"`
- Command string `mapstructure:"command"`
- Share string `mapstructure:"share"`
- Subdomain bool `mapstructure:"subdomain"`
- Healthcheck []appHealthcheckAttributes `mapstructure:"healthcheck"`
- Order int64 `mapstructure:"order"`
- Hidden bool `mapstructure:"hidden"`
- OpenIn string `mapstructure:"open_in"`
+ Name string `mapstructure:"name"`
+ Icon string `mapstructure:"icon"`
+ URL string `mapstructure:"url"`
+ External bool `mapstructure:"external"`
+ Command string `mapstructure:"command"`
+ Share string `mapstructure:"share"`
+ Subdomain bool `mapstructure:"subdomain"`
+ Healthcheck []appHealthcheckAttributes `mapstructure:"healthcheck"`
+ Order int64 `mapstructure:"order"`
+ Hidden bool `mapstructure:"hidden"`
+ OpenIn string `mapstructure:"open_in"`
+ CORSBehavior string `mapstructure:"cors_behavior"`
}
type agentEnvAttributes struct {
@@ -511,6 +512,15 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
openIn = proto.AppOpenIn_TAB
}
+ var corsBehavior proto.AppCORSBehavior
+ switch strings.ToLower(attrs.CORSBehavior) {
+ case "passthru":
+ corsBehavior = proto.AppCORSBehavior_PASSTHRU
+ default:
+ corsBehavior = proto.AppCORSBehavior_SIMPLE
+ logger.Debug(ctx, "cors_behavior not set, defaulting to 'simple'", slog.F("address", convertAddressToLabel(resource.Address)))
+ }
+
for _, agents := range resourceAgents {
for _, agent := range agents {
// Find agents with the matching ID and associate them!
@@ -532,6 +542,7 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
Order: attrs.Order,
Hidden: attrs.Hidden,
OpenIn: openIn,
+ CorsBehavior: corsBehavior,
})
}
}
diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go
index f258f79e36f94..ab6acbf6c2724 100644
--- a/provisionersdk/proto/provisioner.pb.go
+++ b/provisionersdk/proto/provisioner.pb.go
@@ -126,6 +126,52 @@ func (AppSharingLevel) EnumDescriptor() ([]byte, []int) {
return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{1}
}
+type AppCORSBehavior int32
+
+const (
+ AppCORSBehavior_SIMPLE AppCORSBehavior = 0
+ AppCORSBehavior_PASSTHRU AppCORSBehavior = 1
+)
+
+// Enum value maps for AppCORSBehavior.
+var (
+ AppCORSBehavior_name = map[int32]string{
+ 0: "SIMPLE",
+ 1: "PASSTHRU",
+ }
+ AppCORSBehavior_value = map[string]int32{
+ "SIMPLE": 0,
+ "PASSTHRU": 1,
+ }
+)
+
+func (x AppCORSBehavior) Enum() *AppCORSBehavior {
+ p := new(AppCORSBehavior)
+ *p = x
+ return p
+}
+
+func (x AppCORSBehavior) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (AppCORSBehavior) Descriptor() protoreflect.EnumDescriptor {
+ return file_provisionersdk_proto_provisioner_proto_enumTypes[2].Descriptor()
+}
+
+func (AppCORSBehavior) Type() protoreflect.EnumType {
+ return &file_provisionersdk_proto_provisioner_proto_enumTypes[2]
+}
+
+func (x AppCORSBehavior) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use AppCORSBehavior.Descriptor instead.
+func (AppCORSBehavior) EnumDescriptor() ([]byte, []int) {
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{2}
+}
+
type AppOpenIn int32
const (
@@ -160,11 +206,11 @@ func (x AppOpenIn) String() string {
}
func (AppOpenIn) Descriptor() protoreflect.EnumDescriptor {
- return file_provisionersdk_proto_provisioner_proto_enumTypes[2].Descriptor()
+ return file_provisionersdk_proto_provisioner_proto_enumTypes[3].Descriptor()
}
func (AppOpenIn) Type() protoreflect.EnumType {
- return &file_provisionersdk_proto_provisioner_proto_enumTypes[2]
+ return &file_provisionersdk_proto_provisioner_proto_enumTypes[3]
}
func (x AppOpenIn) Number() protoreflect.EnumNumber {
@@ -173,7 +219,7 @@ func (x AppOpenIn) Number() protoreflect.EnumNumber {
// Deprecated: Use AppOpenIn.Descriptor instead.
func (AppOpenIn) EnumDescriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{2}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{3}
}
// WorkspaceTransition is the desired outcome of a build
@@ -210,11 +256,11 @@ func (x WorkspaceTransition) String() string {
}
func (WorkspaceTransition) Descriptor() protoreflect.EnumDescriptor {
- return file_provisionersdk_proto_provisioner_proto_enumTypes[3].Descriptor()
+ return file_provisionersdk_proto_provisioner_proto_enumTypes[4].Descriptor()
}
func (WorkspaceTransition) Type() protoreflect.EnumType {
- return &file_provisionersdk_proto_provisioner_proto_enumTypes[3]
+ return &file_provisionersdk_proto_provisioner_proto_enumTypes[4]
}
func (x WorkspaceTransition) Number() protoreflect.EnumNumber {
@@ -223,7 +269,7 @@ func (x WorkspaceTransition) Number() protoreflect.EnumNumber {
// Deprecated: Use WorkspaceTransition.Descriptor instead.
func (WorkspaceTransition) EnumDescriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{3}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{4}
}
type TimingState int32
@@ -259,11 +305,11 @@ func (x TimingState) String() string {
}
func (TimingState) Descriptor() protoreflect.EnumDescriptor {
- return file_provisionersdk_proto_provisioner_proto_enumTypes[4].Descriptor()
+ return file_provisionersdk_proto_provisioner_proto_enumTypes[5].Descriptor()
}
func (TimingState) Type() protoreflect.EnumType {
- return &file_provisionersdk_proto_provisioner_proto_enumTypes[4]
+ return &file_provisionersdk_proto_provisioner_proto_enumTypes[5]
}
func (x TimingState) Number() protoreflect.EnumNumber {
@@ -272,7 +318,7 @@ func (x TimingState) Number() protoreflect.EnumNumber {
// Deprecated: Use TimingState.Descriptor instead.
func (TimingState) EnumDescriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{4}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{5}
}
// Empty indicates a successful request/response.
@@ -1866,6 +1912,7 @@ type App struct {
Order int64 `protobuf:"varint,10,opt,name=order,proto3" json:"order,omitempty"`
Hidden bool `protobuf:"varint,11,opt,name=hidden,proto3" json:"hidden,omitempty"`
OpenIn AppOpenIn `protobuf:"varint,12,opt,name=open_in,json=openIn,proto3,enum=provisioner.AppOpenIn" json:"open_in,omitempty"`
+ CorsBehavior AppCORSBehavior `protobuf:"varint,13,opt,name=cors_behavior,json=corsBehavior,proto3,enum=provisioner.AppCORSBehavior" json:"cors_behavior,omitempty"`
}
func (x *App) Reset() {
@@ -1984,6 +2031,13 @@ func (x *App) GetOpenIn() AppOpenIn {
return AppOpenIn_WINDOW
}
+func (x *App) GetCorsBehavior() AppCORSBehavior {
+ if x != nil {
+ return x.CorsBehavior
+ }
+ return AppCORSBehavior_SIMPLE
+}
+
// Healthcheck represents configuration for checking for app readiness.
type Healthcheck struct {
state protoimpl.MessageState
@@ -3739,7 +3793,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x61, 0x63, 0x65, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x94,
+ 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd7,
0x03, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69,
0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
@@ -3765,269 +3819,276 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x64, 0x64, 0x65, 0x6e, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x69, 0x6e, 0x18,
0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x6e, 0x52, 0x06, 0x6f,
- 0x70, 0x65, 0x6e, 0x49, 0x6e, 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63,
- 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64,
- 0x22, 0x92, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
- 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74,
- 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a,
- 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x68, 0x69, 0x64,
- 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
- 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e,
- 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61,
- 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
- 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
- 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x69, 0x0a, 0x08, 0x4d, 0x65,
- 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c,
- 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07,
- 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69,
- 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x4c, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12,
- 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
- 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
- 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
- 0x6b, 0x65, 0x79, 0x22, 0x31, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x22, 0xe0, 0x08, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c,
- 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72,
- 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72,
- 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73,
- 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77,
- 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f,
- 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72,
- 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f,
- 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65,
- 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
- 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73,
- 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c,
- 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69,
- 0x64, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
- 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54,
- 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
- 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72,
- 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69,
- 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x6c,
- 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65,
- 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x67, 0x72,
- 0x6f, 0x75, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73,
- 0x12, 0x42, 0x0a, 0x1e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77,
- 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b,
- 0x65, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69,
- 0x63, 0x4b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x76,
- 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x77,
- 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68,
- 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64,
- 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x77, 0x6f, 0x72, 0x6b,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x69,
- 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69,
- 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4e, 0x0a, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x72, 0x62, 0x61, 0x63, 0x5f, 0x72, 0x6f,
- 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76,
- 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x17, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x62, 0x61, 0x63,
- 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x50, 0x72,
- 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
- 0x67, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x67, 0x65, 0x6e,
- 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x72,
- 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41,
- 0x67, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8a, 0x01, 0x0a, 0x06, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
- 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05,
- 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f,
- 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65,
- 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x4c,
- 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61,
- 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f,
- 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
- 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c,
- 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06,
- 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65,
- 0x61, 0x64, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
- 0x65, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70,
- 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65,
- 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72,
- 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
- 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
- 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb5, 0x02, 0x0a,
- 0x0b, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08,
- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74,
- 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
- 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
- 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63,
- 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
- 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65,
- 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69,
- 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61,
- 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x17, 0x65, 0x78, 0x74,
- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f,
- 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
- 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x15, 0x65,
- 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x73, 0x22, 0x99, 0x03, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d,
- 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
- 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
- 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17,
+ 0x70, 0x65, 0x6e, 0x49, 0x6e, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x6f, 0x72, 0x73, 0x5f, 0x62, 0x65,
+ 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x43, 0x4f,
+ 0x52, 0x53, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x0c, 0x63, 0x6f, 0x72, 0x73,
+ 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c,
+ 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f,
+ 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68,
+ 0x6f, 0x6c, 0x64, 0x22, 0x92, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e,
+ 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
+ 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67,
+ 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
+ 0x68, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x69, 0x0a,
+ 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12,
+ 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x4c, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x31, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x22, 0xe0, 0x08, 0x0a, 0x08, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f,
+ 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72,
+ 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72,
+ 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e,
+ 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+ 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77,
+ 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69,
+ 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72,
+ 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61,
+ 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a,
+ 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65,
+ 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a,
+ 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72,
+ 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a,
+ 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65,
+ 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x77,
+ 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a,
+ 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72,
+ 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x77,
+ 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x47, 0x72, 0x6f,
+ 0x75, 0x70, 0x73, 0x12, 0x42, 0x0a, 0x1e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69,
+ 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72,
+ 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, 0x50, 0x75,
+ 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x77, 0x6f, 0x72, 0x6b, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70,
+ 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72,
+ 0x53, 0x73, 0x68, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a,
+ 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x77,
+ 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6c,
+ 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4c,
+ 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4e, 0x0a, 0x1a, 0x77, 0x6f, 0x72, 0x6b,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x72, 0x62, 0x61, 0x63,
+ 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52,
+ 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52,
+ 0x62, 0x61, 0x63, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x70,
+ 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69,
+ 0x73, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x75, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x61,
+ 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x1a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8a, 0x01, 0x0a,
+ 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x6d, 0x70, 0x6c,
+ 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69,
+ 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
+ 0x74, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12,
+ 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x72,
+ 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x0d, 0x50, 0x61,
+ 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70,
+ 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65,
+ 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12,
+ 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
+ 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73,
+ 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61,
+ 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d,
+ 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a,
+ 0x12, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
+ 0xb5, 0x02, 0x0a, 0x0b, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d,
+ 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x52, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
+ 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x17,
0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e,
+ 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
- 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
- 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12,
- 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54,
- 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2d,
- 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2d, 0x0a,
- 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x65,
- 0x73, 0x65, 0x74, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04,
- 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e,
- 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
- 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x22, 0xbe, 0x02, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d,
- 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65,
- 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65,
- 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
- 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72,
- 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
- 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61,
- 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72,
- 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15,
- 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76,
- 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73,
- 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d,
- 0x69, 0x6e, 0x67, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x06, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12,
- 0x30, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72,
- 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12,
- 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
- 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73,
- 0x74, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67,
- 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e,
- 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54,
- 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d,
- 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, 0x0a,
- 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70,
- 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65,
- 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18,
- 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61,
- 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e,
- 0x12, 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70,
- 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70,
- 0x70, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48,
- 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24,
- 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52,
- 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48,
- 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
- 0x65, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, 0x70,
- 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70,
- 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x06, 0x0a,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65,
- 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05,
- 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10,
- 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45,
- 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61,
- 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e,
- 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49,
- 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49,
- 0x43, 0x10, 0x02, 0x2a, 0x35, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x6e,
+ 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72,
+ 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x99, 0x03, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e,
+ 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33,
+ 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
+ 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65,
+ 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12,
+ 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68,
+ 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45,
+ 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69,
+ 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74,
+ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67,
+ 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
+ 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+ 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x12,
+ 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70,
+ 0x6c, 0x61, 0x6e, 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xbe, 0x02, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79,
+ 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14,
+ 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09,
+ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68,
+ 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d,
+ 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
+ 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73,
+ 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74,
+ 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69,
+ 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07,
+ 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x06, 0x54, 0x69, 0x6d, 0x69,
+ 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x65,
+ 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14,
+ 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73,
+ 0x74, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20,
+ 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x12, 0x31, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61,
+ 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61,
+ 0x72, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70,
+ 0x6c, 0x61, 0x6e, 0x12, 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
+ 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52,
+ 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04,
+ 0x74, 0x79, 0x70, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
+ 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67,
+ 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+ 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70,
+ 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70,
+ 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05,
+ 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72,
+ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43,
+ 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79,
+ 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c,
+ 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12,
+ 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e,
+ 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09,
+ 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70,
+ 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05,
+ 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45,
+ 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55,
+ 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x2b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x43, 0x4f, 0x52,
+ 0x53, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x49, 0x4d,
+ 0x50, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x41, 0x53, 0x53, 0x54, 0x48, 0x52,
+ 0x55, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x6e,
0x12, 0x0e, 0x0a, 0x06, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01,
0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x4c, 0x49, 0x4d, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x10,
0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x42, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f,
@@ -4060,116 +4121,118 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte {
return file_provisionersdk_proto_provisioner_proto_rawDescData
}
-var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
+var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 42)
var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{
(LogLevel)(0), // 0: provisioner.LogLevel
(AppSharingLevel)(0), // 1: provisioner.AppSharingLevel
- (AppOpenIn)(0), // 2: provisioner.AppOpenIn
- (WorkspaceTransition)(0), // 3: provisioner.WorkspaceTransition
- (TimingState)(0), // 4: provisioner.TimingState
- (*Empty)(nil), // 5: provisioner.Empty
- (*TemplateVariable)(nil), // 6: provisioner.TemplateVariable
- (*RichParameterOption)(nil), // 7: provisioner.RichParameterOption
- (*RichParameter)(nil), // 8: provisioner.RichParameter
- (*RichParameterValue)(nil), // 9: provisioner.RichParameterValue
- (*Prebuild)(nil), // 10: provisioner.Prebuild
- (*Preset)(nil), // 11: provisioner.Preset
- (*PresetParameter)(nil), // 12: provisioner.PresetParameter
- (*VariableValue)(nil), // 13: provisioner.VariableValue
- (*Log)(nil), // 14: provisioner.Log
- (*InstanceIdentityAuth)(nil), // 15: provisioner.InstanceIdentityAuth
- (*ExternalAuthProviderResource)(nil), // 16: provisioner.ExternalAuthProviderResource
- (*ExternalAuthProvider)(nil), // 17: provisioner.ExternalAuthProvider
- (*Agent)(nil), // 18: provisioner.Agent
- (*ResourcesMonitoring)(nil), // 19: provisioner.ResourcesMonitoring
- (*MemoryResourceMonitor)(nil), // 20: provisioner.MemoryResourceMonitor
- (*VolumeResourceMonitor)(nil), // 21: provisioner.VolumeResourceMonitor
- (*DisplayApps)(nil), // 22: provisioner.DisplayApps
- (*Env)(nil), // 23: provisioner.Env
- (*Script)(nil), // 24: provisioner.Script
- (*Devcontainer)(nil), // 25: provisioner.Devcontainer
- (*App)(nil), // 26: provisioner.App
- (*Healthcheck)(nil), // 27: provisioner.Healthcheck
- (*Resource)(nil), // 28: provisioner.Resource
- (*Module)(nil), // 29: provisioner.Module
- (*Role)(nil), // 30: provisioner.Role
- (*Metadata)(nil), // 31: provisioner.Metadata
- (*Config)(nil), // 32: provisioner.Config
- (*ParseRequest)(nil), // 33: provisioner.ParseRequest
- (*ParseComplete)(nil), // 34: provisioner.ParseComplete
- (*PlanRequest)(nil), // 35: provisioner.PlanRequest
- (*PlanComplete)(nil), // 36: provisioner.PlanComplete
- (*ApplyRequest)(nil), // 37: provisioner.ApplyRequest
- (*ApplyComplete)(nil), // 38: provisioner.ApplyComplete
- (*Timing)(nil), // 39: provisioner.Timing
- (*CancelRequest)(nil), // 40: provisioner.CancelRequest
- (*Request)(nil), // 41: provisioner.Request
- (*Response)(nil), // 42: provisioner.Response
- (*Agent_Metadata)(nil), // 43: provisioner.Agent.Metadata
- nil, // 44: provisioner.Agent.EnvEntry
- (*Resource_Metadata)(nil), // 45: provisioner.Resource.Metadata
- nil, // 46: provisioner.ParseComplete.WorkspaceTagsEntry
- (*timestamppb.Timestamp)(nil), // 47: google.protobuf.Timestamp
+ (AppCORSBehavior)(0), // 2: provisioner.AppCORSBehavior
+ (AppOpenIn)(0), // 3: provisioner.AppOpenIn
+ (WorkspaceTransition)(0), // 4: provisioner.WorkspaceTransition
+ (TimingState)(0), // 5: provisioner.TimingState
+ (*Empty)(nil), // 6: provisioner.Empty
+ (*TemplateVariable)(nil), // 7: provisioner.TemplateVariable
+ (*RichParameterOption)(nil), // 8: provisioner.RichParameterOption
+ (*RichParameter)(nil), // 9: provisioner.RichParameter
+ (*RichParameterValue)(nil), // 10: provisioner.RichParameterValue
+ (*Prebuild)(nil), // 11: provisioner.Prebuild
+ (*Preset)(nil), // 12: provisioner.Preset
+ (*PresetParameter)(nil), // 13: provisioner.PresetParameter
+ (*VariableValue)(nil), // 14: provisioner.VariableValue
+ (*Log)(nil), // 15: provisioner.Log
+ (*InstanceIdentityAuth)(nil), // 16: provisioner.InstanceIdentityAuth
+ (*ExternalAuthProviderResource)(nil), // 17: provisioner.ExternalAuthProviderResource
+ (*ExternalAuthProvider)(nil), // 18: provisioner.ExternalAuthProvider
+ (*Agent)(nil), // 19: provisioner.Agent
+ (*ResourcesMonitoring)(nil), // 20: provisioner.ResourcesMonitoring
+ (*MemoryResourceMonitor)(nil), // 21: provisioner.MemoryResourceMonitor
+ (*VolumeResourceMonitor)(nil), // 22: provisioner.VolumeResourceMonitor
+ (*DisplayApps)(nil), // 23: provisioner.DisplayApps
+ (*Env)(nil), // 24: provisioner.Env
+ (*Script)(nil), // 25: provisioner.Script
+ (*Devcontainer)(nil), // 26: provisioner.Devcontainer
+ (*App)(nil), // 27: provisioner.App
+ (*Healthcheck)(nil), // 28: provisioner.Healthcheck
+ (*Resource)(nil), // 29: provisioner.Resource
+ (*Module)(nil), // 30: provisioner.Module
+ (*Role)(nil), // 31: provisioner.Role
+ (*Metadata)(nil), // 32: provisioner.Metadata
+ (*Config)(nil), // 33: provisioner.Config
+ (*ParseRequest)(nil), // 34: provisioner.ParseRequest
+ (*ParseComplete)(nil), // 35: provisioner.ParseComplete
+ (*PlanRequest)(nil), // 36: provisioner.PlanRequest
+ (*PlanComplete)(nil), // 37: provisioner.PlanComplete
+ (*ApplyRequest)(nil), // 38: provisioner.ApplyRequest
+ (*ApplyComplete)(nil), // 39: provisioner.ApplyComplete
+ (*Timing)(nil), // 40: provisioner.Timing
+ (*CancelRequest)(nil), // 41: provisioner.CancelRequest
+ (*Request)(nil), // 42: provisioner.Request
+ (*Response)(nil), // 43: provisioner.Response
+ (*Agent_Metadata)(nil), // 44: provisioner.Agent.Metadata
+ nil, // 45: provisioner.Agent.EnvEntry
+ (*Resource_Metadata)(nil), // 46: provisioner.Resource.Metadata
+ nil, // 47: provisioner.ParseComplete.WorkspaceTagsEntry
+ (*timestamppb.Timestamp)(nil), // 48: google.protobuf.Timestamp
}
var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{
- 7, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption
- 12, // 1: provisioner.Preset.parameters:type_name -> provisioner.PresetParameter
- 10, // 2: provisioner.Preset.prebuild:type_name -> provisioner.Prebuild
+ 8, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption
+ 13, // 1: provisioner.Preset.parameters:type_name -> provisioner.PresetParameter
+ 11, // 2: provisioner.Preset.prebuild:type_name -> provisioner.Prebuild
0, // 3: provisioner.Log.level:type_name -> provisioner.LogLevel
- 44, // 4: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry
- 26, // 5: provisioner.Agent.apps:type_name -> provisioner.App
- 43, // 6: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata
- 22, // 7: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps
- 24, // 8: provisioner.Agent.scripts:type_name -> provisioner.Script
- 23, // 9: provisioner.Agent.extra_envs:type_name -> provisioner.Env
- 19, // 10: provisioner.Agent.resources_monitoring:type_name -> provisioner.ResourcesMonitoring
- 25, // 11: provisioner.Agent.devcontainers:type_name -> provisioner.Devcontainer
- 20, // 12: provisioner.ResourcesMonitoring.memory:type_name -> provisioner.MemoryResourceMonitor
- 21, // 13: provisioner.ResourcesMonitoring.volumes:type_name -> provisioner.VolumeResourceMonitor
- 27, // 14: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck
+ 45, // 4: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry
+ 27, // 5: provisioner.Agent.apps:type_name -> provisioner.App
+ 44, // 6: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata
+ 23, // 7: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps
+ 25, // 8: provisioner.Agent.scripts:type_name -> provisioner.Script
+ 24, // 9: provisioner.Agent.extra_envs:type_name -> provisioner.Env
+ 20, // 10: provisioner.Agent.resources_monitoring:type_name -> provisioner.ResourcesMonitoring
+ 26, // 11: provisioner.Agent.devcontainers:type_name -> provisioner.Devcontainer
+ 21, // 12: provisioner.ResourcesMonitoring.memory:type_name -> provisioner.MemoryResourceMonitor
+ 22, // 13: provisioner.ResourcesMonitoring.volumes:type_name -> provisioner.VolumeResourceMonitor
+ 28, // 14: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck
1, // 15: provisioner.App.sharing_level:type_name -> provisioner.AppSharingLevel
- 2, // 16: provisioner.App.open_in:type_name -> provisioner.AppOpenIn
- 18, // 17: provisioner.Resource.agents:type_name -> provisioner.Agent
- 45, // 18: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata
- 3, // 19: provisioner.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition
- 30, // 20: provisioner.Metadata.workspace_owner_rbac_roles:type_name -> provisioner.Role
- 6, // 21: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable
- 46, // 22: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry
- 31, // 23: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata
- 9, // 24: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue
- 13, // 25: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue
- 17, // 26: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider
- 28, // 27: provisioner.PlanComplete.resources:type_name -> provisioner.Resource
- 8, // 28: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter
- 16, // 29: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource
- 39, // 30: provisioner.PlanComplete.timings:type_name -> provisioner.Timing
- 29, // 31: provisioner.PlanComplete.modules:type_name -> provisioner.Module
- 11, // 32: provisioner.PlanComplete.presets:type_name -> provisioner.Preset
- 31, // 33: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata
- 28, // 34: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource
- 8, // 35: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter
- 16, // 36: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource
- 39, // 37: provisioner.ApplyComplete.timings:type_name -> provisioner.Timing
- 47, // 38: provisioner.Timing.start:type_name -> google.protobuf.Timestamp
- 47, // 39: provisioner.Timing.end:type_name -> google.protobuf.Timestamp
- 4, // 40: provisioner.Timing.state:type_name -> provisioner.TimingState
- 32, // 41: provisioner.Request.config:type_name -> provisioner.Config
- 33, // 42: provisioner.Request.parse:type_name -> provisioner.ParseRequest
- 35, // 43: provisioner.Request.plan:type_name -> provisioner.PlanRequest
- 37, // 44: provisioner.Request.apply:type_name -> provisioner.ApplyRequest
- 40, // 45: provisioner.Request.cancel:type_name -> provisioner.CancelRequest
- 14, // 46: provisioner.Response.log:type_name -> provisioner.Log
- 34, // 47: provisioner.Response.parse:type_name -> provisioner.ParseComplete
- 36, // 48: provisioner.Response.plan:type_name -> provisioner.PlanComplete
- 38, // 49: provisioner.Response.apply:type_name -> provisioner.ApplyComplete
- 41, // 50: provisioner.Provisioner.Session:input_type -> provisioner.Request
- 42, // 51: provisioner.Provisioner.Session:output_type -> provisioner.Response
- 51, // [51:52] is the sub-list for method output_type
- 50, // [50:51] is the sub-list for method input_type
- 50, // [50:50] is the sub-list for extension type_name
- 50, // [50:50] is the sub-list for extension extendee
- 0, // [0:50] is the sub-list for field type_name
+ 3, // 16: provisioner.App.open_in:type_name -> provisioner.AppOpenIn
+ 2, // 17: provisioner.App.cors_behavior:type_name -> provisioner.AppCORSBehavior
+ 19, // 18: provisioner.Resource.agents:type_name -> provisioner.Agent
+ 46, // 19: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata
+ 4, // 20: provisioner.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition
+ 31, // 21: provisioner.Metadata.workspace_owner_rbac_roles:type_name -> provisioner.Role
+ 7, // 22: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable
+ 47, // 23: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry
+ 32, // 24: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata
+ 10, // 25: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue
+ 14, // 26: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue
+ 18, // 27: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider
+ 29, // 28: provisioner.PlanComplete.resources:type_name -> provisioner.Resource
+ 9, // 29: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter
+ 17, // 30: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource
+ 40, // 31: provisioner.PlanComplete.timings:type_name -> provisioner.Timing
+ 30, // 32: provisioner.PlanComplete.modules:type_name -> provisioner.Module
+ 12, // 33: provisioner.PlanComplete.presets:type_name -> provisioner.Preset
+ 32, // 34: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata
+ 29, // 35: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource
+ 9, // 36: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter
+ 17, // 37: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource
+ 40, // 38: provisioner.ApplyComplete.timings:type_name -> provisioner.Timing
+ 48, // 39: provisioner.Timing.start:type_name -> google.protobuf.Timestamp
+ 48, // 40: provisioner.Timing.end:type_name -> google.protobuf.Timestamp
+ 5, // 41: provisioner.Timing.state:type_name -> provisioner.TimingState
+ 33, // 42: provisioner.Request.config:type_name -> provisioner.Config
+ 34, // 43: provisioner.Request.parse:type_name -> provisioner.ParseRequest
+ 36, // 44: provisioner.Request.plan:type_name -> provisioner.PlanRequest
+ 38, // 45: provisioner.Request.apply:type_name -> provisioner.ApplyRequest
+ 41, // 46: provisioner.Request.cancel:type_name -> provisioner.CancelRequest
+ 15, // 47: provisioner.Response.log:type_name -> provisioner.Log
+ 35, // 48: provisioner.Response.parse:type_name -> provisioner.ParseComplete
+ 37, // 49: provisioner.Response.plan:type_name -> provisioner.PlanComplete
+ 39, // 50: provisioner.Response.apply:type_name -> provisioner.ApplyComplete
+ 42, // 51: provisioner.Provisioner.Session:input_type -> provisioner.Request
+ 43, // 52: provisioner.Provisioner.Session:output_type -> provisioner.Response
+ 52, // [52:53] is the sub-list for method output_type
+ 51, // [51:52] is the sub-list for method input_type
+ 51, // [51:51] is the sub-list for extension type_name
+ 51, // [51:51] is the sub-list for extension extendee
+ 0, // [0:51] is the sub-list for field type_name
}
func init() { file_provisionersdk_proto_provisioner_proto_init() }
@@ -4682,7 +4745,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc,
- NumEnums: 5,
+ NumEnums: 6,
NumMessages: 42,
NumExtensions: 0,
NumServices: 1,
diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto
index 3e6841fb24450..f19efe1f41526 100644
--- a/provisionersdk/proto/provisioner.proto
+++ b/provisionersdk/proto/provisioner.proto
@@ -171,6 +171,11 @@ message VolumeResourceMonitor {
int32 threshold = 3;
}
+enum AppCORSBehavior {
+ SIMPLE = 0;
+ PASSTHRU = 1;
+}
+
message DisplayApps {
bool vscode = 1;
bool vscode_insiders = 2;
@@ -225,6 +230,7 @@ message App {
int64 order = 10;
bool hidden = 11;
AppOpenIn open_in = 12;
+ AppCORSBehavior cors_behavior = 13;
}
// Healthcheck represents configuration for checking for app readiness.
diff --git a/site/e2e/provisionerGenerated.ts b/site/e2e/provisionerGenerated.ts
index cea6f9cb364af..2aed339e96bcb 100644
--- a/site/e2e/provisionerGenerated.ts
+++ b/site/e2e/provisionerGenerated.ts
@@ -22,6 +22,12 @@ export enum AppSharingLevel {
UNRECOGNIZED = -1,
}
+export enum AppCORSBehavior {
+ SIMPLE = 0,
+ PASSTHRU = 1,
+ UNRECOGNIZED = -1,
+}
+
export enum AppOpenIn {
/** @deprecated */
WINDOW = 0,
@@ -246,6 +252,7 @@ export interface App {
order: number;
hidden: boolean;
openIn: AppOpenIn;
+ corsBehavior: AppCORSBehavior;
}
/** Healthcheck represents configuration for checking for app readiness. */
@@ -871,6 +878,9 @@ export const App = {
if (message.openIn !== 0) {
writer.uint32(96).int32(message.openIn);
}
+ if (message.corsBehavior !== 0) {
+ writer.uint32(104).int32(message.corsBehavior);
+ }
return writer;
},
};
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index 0350bce141563..d6cc05e7d1243 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -81,6 +81,11 @@ export const AgentSubsystems: AgentSubsystem[] = [
"exectrace",
];
+// From codersdk/cors_behavior.go
+export type AppCORSBehavior = "passthru" | "simple";
+
+export const AppCORSBehaviors: AppCORSBehavior[] = ["passthru", "simple"];
+
// From codersdk/deployment.go
export interface AppHostResponse {
readonly host: string;
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy