From d58cd664889ad460ef58042af0900fac1ffd8ccf Mon Sep 17 00:00:00 2001 From: Hugo Dutka Date: Fri, 13 Jun 2025 12:30:57 +0000 Subject: [PATCH 1/3] add ai tasks migrations --- .../migrations/000335_ai_tasks.down.sql | 77 +++++++++++++ .../migrations/000335_ai_tasks.up.sql | 103 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 coderd/database/migrations/000335_ai_tasks.down.sql create mode 100644 coderd/database/migrations/000335_ai_tasks.up.sql diff --git a/coderd/database/migrations/000335_ai_tasks.down.sql b/coderd/database/migrations/000335_ai_tasks.down.sql new file mode 100644 index 0000000000000..b4684184b182b --- /dev/null +++ b/coderd/database/migrations/000335_ai_tasks.down.sql @@ -0,0 +1,77 @@ +DROP VIEW workspace_build_with_user; + +DROP VIEW template_version_with_user; + +DROP INDEX idx_template_versions_has_ai_task; + +ALTER TABLE + template_versions DROP COLUMN has_ai_task; + +ALTER TABLE + workspace_builds DROP CONSTRAINT workspace_builds_ai_tasks_sidebar_app_id_fkey; + +ALTER TABLE + workspace_builds DROP COLUMN ai_tasks_sidebar_app_id; + +ALTER TABLE + workspace_builds DROP COLUMN has_ai_task; + +-- Recreate `workspace_build_with_user` as defined in dump.sql +CREATE VIEW workspace_build_with_user AS +SELECT + workspace_builds.id, + workspace_builds.created_at, + workspace_builds.updated_at, + workspace_builds.workspace_id, + workspace_builds.template_version_id, + workspace_builds.build_number, + workspace_builds.transition, + workspace_builds.initiator_id, + workspace_builds.provisioner_state, + workspace_builds.job_id, + workspace_builds.deadline, + workspace_builds.reason, + workspace_builds.daily_cost, + workspace_builds.max_deadline, + workspace_builds.template_version_preset_id, + COALESCE(visible_users.avatar_url, '' :: text) AS initiator_by_avatar_url, + COALESCE(visible_users.username, '' :: text) AS initiator_by_username, + COALESCE(visible_users.name, '' :: text) AS initiator_by_name +FROM + ( + workspace_builds + LEFT JOIN visible_users ON ( + (workspace_builds.initiator_id = visible_users.id) + ) + ); + +COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.'; + +-- Recreate `template_version_with_user` as defined in dump.sql +CREATE VIEW template_version_with_user AS +SELECT + template_versions.id, + template_versions.template_id, + template_versions.organization_id, + template_versions.created_at, + template_versions.updated_at, + template_versions.name, + template_versions.readme, + template_versions.job_id, + template_versions.created_by, + template_versions.external_auth_providers, + template_versions.message, + template_versions.archived, + template_versions.source_example_id, + COALESCE(visible_users.avatar_url, '' :: text) AS created_by_avatar_url, + COALESCE(visible_users.username, '' :: text) AS created_by_username, + COALESCE(visible_users.name, '' :: text) AS created_by_name +FROM + ( + template_versions + LEFT JOIN visible_users ON ( + (template_versions.created_by = visible_users.id) + ) + ); + +COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.'; diff --git a/coderd/database/migrations/000335_ai_tasks.up.sql b/coderd/database/migrations/000335_ai_tasks.up.sql new file mode 100644 index 0000000000000..4aed761b568a5 --- /dev/null +++ b/coderd/database/migrations/000335_ai_tasks.up.sql @@ -0,0 +1,103 @@ +-- Determines if a coder_ai_task resource was included in a +-- workspace build. +ALTER TABLE + workspace_builds +ADD + COLUMN has_ai_task BOOLEAN NOT NULL DEFAULT FALSE; + +-- The app that is displayed in the ai tasks sidebar. +ALTER TABLE + workspace_builds +ADD + COLUMN ai_tasks_sidebar_app_id UUID DEFAULT NULL; + +ALTER TABLE + workspace_builds +ADD + CONSTRAINT workspace_builds_ai_tasks_sidebar_app_id_fkey FOREIGN KEY (ai_tasks_sidebar_app_id) REFERENCES workspace_apps(id); + +-- Determines if a coder_ai_task resource is defined in a template version. +ALTER TABLE + template_versions +ADD + COLUMN has_ai_task BOOLEAN NOT NULL DEFAULT FALSE; + +-- The Tasks tab will be rendered in the UI only if there's at least one template version with has_ai_task set to true. +-- The query to determine this will be run on every UI render, and this index speeds it up. +-- SELECT EXISTS (SELECT 1 FROM template_versions WHERE has_ai_task = TRUE); +CREATE INDEX idx_template_versions_has_ai_task ON template_versions USING btree (has_ai_task); + +DROP VIEW workspace_build_with_user; + +-- We're adding the has_ai_task and ai_tasks_sidebar_app_id columns. +CREATE VIEW workspace_build_with_user AS +SELECT + workspace_builds.id, + workspace_builds.created_at, + workspace_builds.updated_at, + workspace_builds.workspace_id, + workspace_builds.template_version_id, + workspace_builds.build_number, + workspace_builds.transition, + workspace_builds.initiator_id, + workspace_builds.provisioner_state, + workspace_builds.job_id, + workspace_builds.deadline, + workspace_builds.reason, + workspace_builds.daily_cost, + workspace_builds.max_deadline, + workspace_builds.template_version_preset_id, + workspace_builds.has_ai_task, + workspace_builds.ai_tasks_sidebar_app_id, + COALESCE( + visible_users.avatar_url, + '' :: text + ) AS initiator_by_avatar_url, + COALESCE( + visible_users.username, + '' :: text + ) AS initiator_by_username, + COALESCE(visible_users.name, '' :: text) AS initiator_by_name +FROM + ( + workspace_builds + LEFT JOIN visible_users ON ( + ( + workspace_builds.initiator_id = visible_users.id + ) + ) + ); + +COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.'; + +DROP VIEW template_version_with_user; + +-- We're adding the has_ai_task column. +CREATE VIEW template_version_with_user AS +SELECT + template_versions.id, + template_versions.template_id, + template_versions.organization_id, + template_versions.created_at, + template_versions.updated_at, + template_versions.name, + template_versions.readme, + template_versions.job_id, + template_versions.created_by, + template_versions.external_auth_providers, + template_versions.message, + template_versions.archived, + template_versions.source_example_id, + template_versions.has_ai_task, + COALESCE(visible_users.avatar_url, '' :: text) AS created_by_avatar_url, + COALESCE(visible_users.username, '' :: text) AS created_by_username, + COALESCE(visible_users.name, '' :: text) AS created_by_name +FROM + ( + template_versions + LEFT JOIN visible_users ON ( + (template_versions.created_by = visible_users.id) + ) + ); + +COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.'; From 16ed8280bbb6d9631fe6dbc193b2bf886fa486a8 Mon Sep 17 00:00:00 2001 From: Hugo Dutka Date: Fri, 13 Jun 2025 12:53:31 +0000 Subject: [PATCH 2/3] edits before make gen --- coderd/database/sqlc.yaml | 2 ++ enterprise/audit/table.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml index b43281a3f1051..79b4b21f4d83f 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 + has_ai_task: HasAITask + ai_tasks_sidebar_app_id: AITasksSidebarAppID rules: - name: do-not-use-public-schema-in-queries message: "do not use public schema in queries" diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index d52632996ba26..ffb79810ee2c3 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -135,6 +135,7 @@ var auditableResourcesTypes = map[any]map[string]Action{ "created_by_name": ActionIgnore, "archived": ActionTrack, "source_example_id": ActionIgnore, // Never changes. + "has_ai_task": ActionIgnore, // Never changes. }, &database.User{}: { "id": ActionTrack, @@ -193,6 +194,8 @@ var auditableResourcesTypes = map[any]map[string]Action{ "initiator_by_username": ActionIgnore, "initiator_by_name": ActionIgnore, "template_version_preset_id": ActionIgnore, // Never changes. + "has_ai_task": ActionIgnore, // Never changes. + "ai_tasks_sidebar_app_id": ActionIgnore, // Never changes. }, &database.AuditableGroup{}: { "id": ActionTrack, From 50f100822a1246c33d944fe7a902ddba3e67db83 Mon Sep 17 00:00:00 2001 From: Hugo Dutka Date: Fri, 13 Jun 2025 12:56:41 +0000 Subject: [PATCH 3/3] make gen --- coderd/database/dump.sql | 15 +++++- coderd/database/foreign_key_constraint.go | 1 + coderd/database/models.go | 6 +++ coderd/database/queries.sql.go | 63 ++++++++++++++++------- docs/admin/security/audit-logs.md | 4 +- 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index e4cee2333efc4..b37ffe45e95c6 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -1553,7 +1553,8 @@ CREATE TABLE template_versions ( external_auth_providers jsonb DEFAULT '[]'::jsonb NOT NULL, message character varying(1048576) DEFAULT ''::character varying NOT NULL, archived boolean DEFAULT false NOT NULL, - source_example_id text + source_example_id text, + has_ai_task boolean DEFAULT false NOT NULL ); COMMENT ON COLUMN template_versions.external_auth_providers IS 'IDs of External auth providers for a specific template version'; @@ -1583,6 +1584,7 @@ CREATE VIEW template_version_with_user AS template_versions.message, template_versions.archived, template_versions.source_example_id, + template_versions.has_ai_task, COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url, COALESCE(visible_users.username, ''::text) AS created_by_username, COALESCE(visible_users.name, ''::text) AS created_by_name @@ -2080,7 +2082,9 @@ CREATE TABLE workspace_builds ( reason build_reason DEFAULT 'initiator'::build_reason NOT NULL, daily_cost integer DEFAULT 0 NOT NULL, max_deadline timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL, - template_version_preset_id uuid + template_version_preset_id uuid, + has_ai_task boolean DEFAULT false NOT NULL, + ai_tasks_sidebar_app_id uuid ); CREATE VIEW workspace_build_with_user AS @@ -2099,6 +2103,8 @@ CREATE VIEW workspace_build_with_user AS workspace_builds.daily_cost, workspace_builds.max_deadline, workspace_builds.template_version_preset_id, + workspace_builds.has_ai_task, + workspace_builds.ai_tasks_sidebar_app_id, COALESCE(visible_users.avatar_url, ''::text) AS initiator_by_avatar_url, COALESCE(visible_users.username, ''::text) AS initiator_by_username, COALESCE(visible_users.name, ''::text) AS initiator_by_name @@ -2667,6 +2673,8 @@ CREATE INDEX idx_tailnet_tunnels_dst_id ON tailnet_tunnels USING hash (dst_id); CREATE INDEX idx_tailnet_tunnels_src_id ON tailnet_tunnels USING hash (src_id); +CREATE INDEX idx_template_versions_has_ai_task ON template_versions USING btree (has_ai_task); + CREATE UNIQUE INDEX idx_unique_preset_name ON template_version_presets USING btree (name, template_version_id); CREATE INDEX idx_user_deleted_deleted_at ON user_deleted USING btree (deleted_at); @@ -3063,6 +3071,9 @@ ALTER TABLE ONLY workspace_apps ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE; +ALTER TABLE ONLY workspace_builds + ADD CONSTRAINT workspace_builds_ai_tasks_sidebar_app_id_fkey FOREIGN KEY (ai_tasks_sidebar_app_id) REFERENCES workspace_apps(id); + ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; diff --git a/coderd/database/foreign_key_constraint.go b/coderd/database/foreign_key_constraint.go index d6b87ddff5376..eaec2d2495337 100644 --- a/coderd/database/foreign_key_constraint.go +++ b/coderd/database/foreign_key_constraint.go @@ -82,6 +82,7 @@ const ( ForeignKeyWorkspaceAppStatusesWorkspaceID ForeignKeyConstraint = "workspace_app_statuses_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id); ForeignKeyWorkspaceAppsAgentID ForeignKeyConstraint = "workspace_apps_agent_id_fkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE; ForeignKeyWorkspaceBuildParametersWorkspaceBuildID ForeignKeyConstraint = "workspace_build_parameters_workspace_build_id_fkey" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE; + ForeignKeyWorkspaceBuildsAiTasksSidebarAppID ForeignKeyConstraint = "workspace_builds_ai_tasks_sidebar_app_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_ai_tasks_sidebar_app_id_fkey FOREIGN KEY (ai_tasks_sidebar_app_id) REFERENCES workspace_apps(id); ForeignKeyWorkspaceBuildsJobID ForeignKeyConstraint = "workspace_builds_job_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; ForeignKeyWorkspaceBuildsTemplateVersionID ForeignKeyConstraint = "workspace_builds_template_version_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE; ForeignKeyWorkspaceBuildsTemplateVersionPresetID ForeignKeyConstraint = "workspace_builds_template_version_preset_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL; diff --git a/coderd/database/models.go b/coderd/database/models.go index 69ae70b6c3bd3..2533c9a843501 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -3355,6 +3355,7 @@ type TemplateVersion struct { Message string `db:"message" json:"message"` Archived bool `db:"archived" json:"archived"` SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"` + HasAITask bool `db:"has_ai_task" json:"has_ai_task"` CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"` CreatedByUsername string `db:"created_by_username" json:"created_by_username"` CreatedByName string `db:"created_by_name" json:"created_by_name"` @@ -3431,6 +3432,7 @@ type TemplateVersionTable struct { Message string `db:"message" json:"message"` Archived bool `db:"archived" json:"archived"` SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"` + HasAITask bool `db:"has_ai_task" json:"has_ai_task"` } type TemplateVersionTerraformValue struct { @@ -3845,6 +3847,8 @@ type WorkspaceBuild struct { DailyCost int32 `db:"daily_cost" json:"daily_cost"` MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"` TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"` + HasAITask bool `db:"has_ai_task" json:"has_ai_task"` + AITasksSidebarAppID uuid.NullUUID `db:"ai_tasks_sidebar_app_id" json:"ai_tasks_sidebar_app_id"` InitiatorByAvatarUrl string `db:"initiator_by_avatar_url" json:"initiator_by_avatar_url"` InitiatorByUsername string `db:"initiator_by_username" json:"initiator_by_username"` InitiatorByName string `db:"initiator_by_name" json:"initiator_by_name"` @@ -3874,6 +3878,8 @@ type WorkspaceBuildTable struct { DailyCost int32 `db:"daily_cost" json:"daily_cost"` MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"` TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"` + HasAITask bool `db:"has_ai_task" json:"has_ai_task"` + AITasksSidebarAppID uuid.NullUUID `db:"ai_tasks_sidebar_app_id" json:"ai_tasks_sidebar_app_id"` } type WorkspaceLatestBuild struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index eec91c7586d61..92c912a55705a 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -11349,7 +11349,7 @@ FROM -- Scope an archive to a single template and ignore already archived template versions ( SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task FROM template_versions WHERE @@ -11450,7 +11450,7 @@ func (q *sqlQuerier) ArchiveUnusedTemplateVersions(ctx context.Context, arg Arch const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11488,6 +11488,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11497,7 +11498,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11521,6 +11522,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) ( &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11530,7 +11532,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) ( const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11554,6 +11556,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11563,7 +11566,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11593,6 +11596,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context, &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11602,7 +11606,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context, const getTemplateVersionsByIDs = `-- name: GetTemplateVersionsByIDs :many SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11632,6 +11636,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11651,7 +11656,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many SELECT - id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name + id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE @@ -11728,6 +11733,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -11746,7 +11752,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge } const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many -SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE created_at > $1 +SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE created_at > $1 ` func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) { @@ -11772,6 +11778,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create &i.Message, &i.Archived, &i.SourceExampleID, + &i.HasAITask, &i.CreatedByAvatarURL, &i.CreatedByUsername, &i.CreatedByName, @@ -14178,7 +14185,7 @@ const getWorkspaceAgentAndLatestBuildByAuthToken = `-- name: GetWorkspaceAgentAn SELECT workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, workspaces.next_start_at, workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.expanded_directory, workspace_agents.logs_length, workspace_agents.logs_overflowed, workspace_agents.started_at, workspace_agents.ready_at, workspace_agents.subsystems, workspace_agents.display_apps, workspace_agents.api_version, workspace_agents.display_order, workspace_agents.parent_id, workspace_agents.api_key_scope, - workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.template_version_preset_id, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username, workspace_build_with_user.initiator_by_name + workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.template_version_preset_id, workspace_build_with_user.has_ai_task, workspace_build_with_user.ai_tasks_sidebar_app_id, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username, workspace_build_with_user.initiator_by_name FROM workspace_agents JOIN @@ -14284,6 +14291,8 @@ func (q *sqlQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(ctx context.Cont &i.WorkspaceBuild.DailyCost, &i.WorkspaceBuild.MaxDeadline, &i.WorkspaceBuild.TemplateVersionPresetID, + &i.WorkspaceBuild.HasAITask, + &i.WorkspaceBuild.AITasksSidebarAppID, &i.WorkspaceBuild.InitiatorByAvatarUrl, &i.WorkspaceBuild.InitiatorByUsername, &i.WorkspaceBuild.InitiatorByName, @@ -16853,7 +16862,7 @@ func (q *sqlQuerier) InsertWorkspaceBuildParameters(ctx context.Context, arg Ins } const getActiveWorkspaceBuildsByTemplateID = `-- name: GetActiveWorkspaceBuildsByTemplateID :many -SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name +SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_tasks_sidebar_app_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name FROM ( SELECT workspace_id, MAX(build_number) as max_build_number @@ -16908,6 +16917,8 @@ func (q *sqlQuerier) GetActiveWorkspaceBuildsByTemplateID(ctx context.Context, t &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17007,7 +17018,7 @@ func (q *sqlQuerier) GetFailedWorkspaceBuildsByTemplateID(ctx context.Context, a const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one SELECT - id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name + id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user AS workspace_builds WHERE @@ -17037,6 +17048,8 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17045,7 +17058,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w } const getLatestWorkspaceBuilds = `-- name: GetLatestWorkspaceBuilds :many -SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name +SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_tasks_sidebar_app_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name FROM ( SELECT workspace_id, MAX(build_number) as max_build_number @@ -17084,6 +17097,8 @@ func (q *sqlQuerier) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceB &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17102,7 +17117,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceB } const getLatestWorkspaceBuildsByWorkspaceIDs = `-- name: GetLatestWorkspaceBuildsByWorkspaceIDs :many -SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name +SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_tasks_sidebar_app_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name FROM ( SELECT workspace_id, MAX(build_number) as max_build_number @@ -17143,6 +17158,8 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17162,7 +17179,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, const getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one SELECT - id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name + id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user AS workspace_builds WHERE @@ -17190,6 +17207,8 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17199,7 +17218,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one SELECT - id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name + id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user AS workspace_builds WHERE @@ -17227,6 +17246,8 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17236,7 +17257,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU const getWorkspaceBuildByWorkspaceIDAndBuildNumber = `-- name: GetWorkspaceBuildByWorkspaceIDAndBuildNumber :one SELECT - id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name + id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user AS workspace_builds WHERE @@ -17268,6 +17289,8 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Co &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17344,7 +17367,7 @@ func (q *sqlQuerier) GetWorkspaceBuildStatsByTemplates(ctx context.Context, sinc const getWorkspaceBuildsByWorkspaceID = `-- name: GetWorkspaceBuildsByWorkspaceID :many SELECT - id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name + id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user AS workspace_builds WHERE @@ -17415,6 +17438,8 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, @@ -17433,7 +17458,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge } const getWorkspaceBuildsCreatedAfter = `-- name: GetWorkspaceBuildsCreatedAfter :many -SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user WHERE created_at > $1 +SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_tasks_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user WHERE created_at > $1 ` func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error) { @@ -17461,6 +17486,8 @@ func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, created &i.DailyCost, &i.MaxDeadline, &i.TemplateVersionPresetID, + &i.HasAITask, + &i.AITasksSidebarAppID, &i.InitiatorByAvatarUrl, &i.InitiatorByUsername, &i.InitiatorByName, diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md index 4ed07cdc9dfb6..080e864fcb866 100644 --- a/docs/admin/security/audit-logs.md +++ b/docs/admin/security/audit-logs.md @@ -27,11 +27,11 @@ We track the following resources: | OrganizationSyncSettings
| |
FieldTracked
assign_defaulttrue
fieldtrue
mappingtrue
| | RoleSyncSettings
| |
FieldTracked
fieldtrue
mappingtrue
| | Template
write, delete | |
FieldTracked
active_version_idtrue
activity_bumptrue
allow_user_autostarttrue
allow_user_autostoptrue
allow_user_cancel_workspace_jobstrue
autostart_block_days_of_weektrue
autostop_requirement_days_of_weektrue
autostop_requirement_weekstrue
created_atfalse
created_bytrue
created_by_avatar_urlfalse
created_by_namefalse
created_by_usernamefalse
default_ttltrue
deletedfalse
deprecatedtrue
descriptiontrue
display_nametrue
failure_ttltrue
group_acltrue
icontrue
idtrue
max_port_sharing_leveltrue
nametrue
organization_display_namefalse
organization_iconfalse
organization_idfalse
organization_namefalse
provisionertrue
require_active_versiontrue
time_til_dormanttrue
time_til_dormant_autodeletetrue
updated_atfalse
use_classic_parameter_flowtrue
user_acltrue
| -| TemplateVersion
create, write | |
FieldTracked
archivedtrue
created_atfalse
created_bytrue
created_by_avatar_urlfalse
created_by_namefalse
created_by_usernamefalse
external_auth_providersfalse
idtrue
job_idfalse
messagefalse
nametrue
organization_idfalse
readmetrue
source_example_idfalse
template_idtrue
updated_atfalse
| +| TemplateVersion
create, write | |
FieldTracked
archivedtrue
created_atfalse
created_bytrue
created_by_avatar_urlfalse
created_by_namefalse
created_by_usernamefalse
external_auth_providersfalse
has_ai_taskfalse
idtrue
job_idfalse
messagefalse
nametrue
organization_idfalse
readmetrue
source_example_idfalse
template_idtrue
updated_atfalse
| | User
create, write, delete | |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
github_com_user_idfalse
hashed_one_time_passcodefalse
hashed_passwordtrue
idtrue
is_systemtrue
last_seen_atfalse
login_typetrue
nametrue
one_time_passcode_expires_attrue
quiet_hours_scheduletrue
rbac_rolestrue
statustrue
updated_atfalse
usernametrue
| | WorkspaceAgent
connect, disconnect | |
FieldTracked
api_key_scopefalse
api_versionfalse
architecturefalse
auth_instance_idfalse
auth_tokenfalse
connection_timeout_secondsfalse
created_atfalse
directoryfalse
disconnected_atfalse
display_appsfalse
display_orderfalse
environment_variablesfalse
expanded_directoryfalse
first_connected_atfalse
idfalse
instance_metadatafalse
last_connected_atfalse
last_connected_replica_idfalse
lifecycle_statefalse
logs_lengthfalse
logs_overflowedfalse
motd_filefalse
namefalse
operating_systemfalse
parent_idfalse
ready_atfalse
resource_idfalse
resource_metadatafalse
started_atfalse
subsystemsfalse
troubleshooting_urlfalse
updated_atfalse
versionfalse
| | WorkspaceApp
open, close | |
FieldTracked
agent_idfalse
commandfalse
created_atfalse
display_groupfalse
display_namefalse
display_orderfalse
externalfalse
healthfalse
healthcheck_intervalfalse
healthcheck_thresholdfalse
healthcheck_urlfalse
hiddenfalse
iconfalse
idfalse
open_infalse
sharing_levelfalse
slugfalse
subdomainfalse
urlfalse
| -| WorkspaceBuild
start, stop | |
FieldTracked
build_numberfalse
created_atfalse
daily_costfalse
deadlinefalse
idfalse
initiator_by_avatar_urlfalse
initiator_by_namefalse
initiator_by_usernamefalse
initiator_idfalse
job_idfalse
max_deadlinefalse
provisioner_statefalse
reasonfalse
template_version_idtrue
template_version_preset_idfalse
transitionfalse
updated_atfalse
workspace_idfalse
| +| WorkspaceBuild
start, stop | |
FieldTracked
ai_tasks_sidebar_app_idfalse
build_numberfalse
created_atfalse
daily_costfalse
deadlinefalse
has_ai_taskfalse
idfalse
initiator_by_avatar_urlfalse
initiator_by_namefalse
initiator_by_usernamefalse
initiator_idfalse
job_idfalse
max_deadlinefalse
provisioner_statefalse
reasonfalse
template_version_idtrue
template_version_preset_idfalse
transitionfalse
updated_atfalse
workspace_idfalse
| | WorkspaceProxy
| |
FieldTracked
created_attrue
deletedfalse
derp_enabledtrue
derp_onlytrue
display_nametrue
icontrue
idtrue
nametrue
region_idtrue
token_hashed_secrettrue
updated_atfalse
urltrue
versiontrue
wildcard_hostnametrue
| | WorkspaceTable
| |
FieldTracked
automatic_updatestrue
autostart_scheduletrue
created_atfalse
deletedfalse
deleting_attrue
dormant_attrue
favoritetrue
idtrue
last_used_atfalse
nametrue
next_start_attrue
organization_idfalse
owner_idtrue
template_idtrue
ttltrue
updated_atfalse
|