diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index 617678ab99..0fc64ef9b0 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -17247,7 +17247,8 @@ const docTemplate = `{
"idp_sync_settings_group",
"idp_sync_settings_role",
"workspace_agent",
- "workspace_app"
+ "workspace_app",
+ "task"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@@ -17274,7 +17275,8 @@ const docTemplate = `{
"ResourceTypeIdpSyncSettingsGroup",
"ResourceTypeIdpSyncSettingsRole",
"ResourceTypeWorkspaceAgent",
- "ResourceTypeWorkspaceApp"
+ "ResourceTypeWorkspaceApp",
+ "ResourceTypeTask"
]
},
"codersdk.Response": {
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index 83a51e31b8..867e5e5818 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -15759,7 +15759,8 @@
"idp_sync_settings_group",
"idp_sync_settings_role",
"workspace_agent",
- "workspace_app"
+ "workspace_app",
+ "task"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@@ -15786,7 +15787,8 @@
"ResourceTypeIdpSyncSettingsGroup",
"ResourceTypeIdpSyncSettingsRole",
"ResourceTypeWorkspaceAgent",
- "ResourceTypeWorkspaceApp"
+ "ResourceTypeWorkspaceApp",
+ "ResourceTypeTask"
]
},
"codersdk.Response": {
diff --git a/coderd/audit.go b/coderd/audit.go
index e8d7c4dfe9..e43ed1c512 100644
--- a/coderd/audit.go
+++ b/coderd/audit.go
@@ -420,6 +420,14 @@ func (api *API) auditLogIsResourceDeleted(ctx context.Context, alog database.Get
api.Logger.Error(ctx, "unable to fetch oauth2 app secret", slog.Error(err))
}
return false
+ case database.ResourceTypeTask:
+ task, err := api.Database.GetTaskByID(ctx, alog.AuditLog.ResourceID)
+ if xerrors.Is(err, sql.ErrNoRows) {
+ return true
+ } else if err != nil {
+ api.Logger.Error(ctx, "unable to fetch task", slog.Error(err))
+ }
+ return task.DeletedAt.Valid && task.DeletedAt.Time.Before(time.Now())
default:
return false
}
@@ -496,6 +504,17 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
}
return fmt.Sprintf("/deployment/oauth2-provider/apps/%s", secret.AppID)
+ case database.ResourceTypeTask:
+ task, err := api.Database.GetTaskByID(ctx, alog.AuditLog.ResourceID)
+ if err != nil {
+ return ""
+ }
+ workspace, err := api.Database.GetWorkspaceByID(ctx, task.WorkspaceID.UUID)
+ if err != nil {
+ return ""
+ }
+ return fmt.Sprintf("/tasks/%s/%s", workspace.OwnerName, task.Name)
+
default:
return ""
}
diff --git a/coderd/audit/diff.go b/coderd/audit/diff.go
index b8139bb63b..c14dbc392f 100644
--- a/coderd/audit/diff.go
+++ b/coderd/audit/diff.go
@@ -31,7 +31,8 @@ type Auditable interface {
database.NotificationTemplate |
idpsync.OrganizationSyncSettings |
idpsync.GroupSyncSettings |
- idpsync.RoleSyncSettings
+ idpsync.RoleSyncSettings |
+ database.TaskTable
}
// Map is a map of changed fields in an audited resource. It maps field names to
diff --git a/coderd/audit/request.go b/coderd/audit/request.go
index a973bdb915..20aa89f6a8 100644
--- a/coderd/audit/request.go
+++ b/coderd/audit/request.go
@@ -131,6 +131,8 @@ func ResourceTarget[T Auditable](tgt T) string {
return "Organization Group Sync"
case idpsync.RoleSyncSettings:
return "Organization Role Sync"
+ case database.TaskTable:
+ return typed.Name
default:
panic(fmt.Sprintf("unknown resource %T for ResourceTarget", tgt))
}
@@ -193,6 +195,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return noID // Org field on audit log has org id
case idpsync.RoleSyncSettings:
return noID // Org field on audit log has org id
+ case database.TaskTable:
+ return typed.ID
default:
panic(fmt.Sprintf("unknown resource %T for ResourceID", tgt))
}
@@ -246,6 +250,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeIdpSyncSettingsRole
case idpsync.GroupSyncSettings:
return database.ResourceTypeIdpSyncSettingsGroup
+ case database.TaskTable:
+ return database.ResourceTypeTask
default:
panic(fmt.Sprintf("unknown resource %T for ResourceType", typed))
}
@@ -302,6 +308,8 @@ func ResourceRequiresOrgID[T Auditable]() bool {
return true
case idpsync.RoleSyncSettings:
return true
+ case database.TaskTable:
+ return true
default:
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID", tgt))
}
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 5b23e7b288..71e2845d1c 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -460,7 +460,8 @@ CREATE TYPE resource_type AS ENUM (
'idp_sync_settings_role',
'workspace_agent',
'workspace_app',
- 'prebuilds_settings'
+ 'prebuilds_settings',
+ 'task'
);
CREATE TYPE startup_script_behavior AS ENUM (
diff --git a/coderd/database/migrations/000381_add_task_audit.down.sql b/coderd/database/migrations/000381_add_task_audit.down.sql
new file mode 100644
index 0000000000..362f597df0
--- /dev/null
+++ b/coderd/database/migrations/000381_add_task_audit.down.sql
@@ -0,0 +1 @@
+-- Nothing to do
diff --git a/coderd/database/migrations/000381_add_task_audit.up.sql b/coderd/database/migrations/000381_add_task_audit.up.sql
new file mode 100644
index 0000000000..006391ac1f
--- /dev/null
+++ b/coderd/database/migrations/000381_add_task_audit.up.sql
@@ -0,0 +1 @@
+ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'task';
diff --git a/coderd/database/models.go b/coderd/database/models.go
index 8f62f1a307..741d70f9d2 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -2670,6 +2670,7 @@ const (
ResourceTypeWorkspaceAgent ResourceType = "workspace_agent"
ResourceTypeWorkspaceApp ResourceType = "workspace_app"
ResourceTypePrebuildsSettings ResourceType = "prebuilds_settings"
+ ResourceTypeTask ResourceType = "task"
)
func (e *ResourceType) Scan(src interface{}) error {
@@ -2733,7 +2734,8 @@ func (e ResourceType) Valid() bool {
ResourceTypeIdpSyncSettingsRole,
ResourceTypeWorkspaceAgent,
ResourceTypeWorkspaceApp,
- ResourceTypePrebuildsSettings:
+ ResourceTypePrebuildsSettings,
+ ResourceTypeTask:
return true
}
return false
@@ -2766,6 +2768,7 @@ func AllResourceTypeValues() []ResourceType {
ResourceTypeWorkspaceAgent,
ResourceTypeWorkspaceApp,
ResourceTypePrebuildsSettings,
+ ResourceTypeTask,
}
}
diff --git a/codersdk/audit.go b/codersdk/audit.go
index 1e529202b5..0b2eca7d79 100644
--- a/codersdk/audit.go
+++ b/codersdk/audit.go
@@ -44,6 +44,7 @@ const (
// Deprecated: Workspace App connections are now included in the
// connection log.
ResourceTypeWorkspaceApp ResourceType = "workspace_app"
+ ResourceTypeTask ResourceType = "task"
)
func (r ResourceType) FriendlyString() string {
@@ -100,6 +101,8 @@ func (r ResourceType) FriendlyString() string {
return "workspace agent"
case ResourceTypeWorkspaceApp:
return "workspace app"
+ case ResourceTypeTask:
+ return "task"
default:
return "unknown"
}
diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md
index 2c72528f38..387bdd9836 100644
--- a/docs/admin/security/audit-logs.md
+++ b/docs/admin/security/audit-logs.md
@@ -32,6 +32,7 @@ We track the following resources:
| OrganizationSyncSettings
|
| Field | Tracked |
| | assign_default | true |
| field | true |
| mapping | true |
|
| PrebuildsSettings
| | Field | Tracked |
| | id | false |
| reconciliation_paused | true |
|
| RoleSyncSettings
| | Field | Tracked |
| | field | true |
| mapping | true |
|
+| TaskTable
| | Field | Tracked |
| | created_at | false |
| deleted_at | false |
| id | true |
| name | true |
| organization_id | false |
| owner_id | true |
| prompt | true |
| template_parameters | true |
| template_version_id | true |
| workspace_id | true |
|
| Template
write, delete | | Field | Tracked |
| | active_version_id | true |
| activity_bump | true |
| allow_user_autostart | true |
| allow_user_autostop | true |
| allow_user_cancel_workspace_jobs | true |
| autostart_block_days_of_week | true |
| autostop_requirement_days_of_week | true |
| autostop_requirement_weeks | true |
| cors_behavior | true |
| created_at | false |
| created_by | true |
| created_by_avatar_url | false |
| created_by_name | false |
| created_by_username | false |
| default_ttl | true |
| deleted | false |
| deprecated | true |
| description | true |
| display_name | true |
| failure_ttl | true |
| group_acl | true |
| icon | true |
| id | true |
| max_port_sharing_level | true |
| name | true |
| organization_display_name | false |
| organization_icon | false |
| organization_id | false |
| organization_name | false |
| provisioner | true |
| require_active_version | true |
| time_til_dormant | true |
| time_til_dormant_autodelete | true |
| updated_at | false |
| use_classic_parameter_flow | true |
| user_acl | true |
|
| TemplateVersion
create, write | | Field | Tracked |
| | archived | true |
| created_at | false |
| created_by | true |
| created_by_avatar_url | false |
| created_by_name | false |
| created_by_username | false |
| external_auth_providers | false |
| has_ai_task | false |
| has_external_agent | 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 |
|
| User
create, 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 |
|
diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md
index 4c8fcba929..526deff931 100644
--- a/docs/reference/api/schemas.md
+++ b/docs/reference/api/schemas.md
@@ -7367,6 +7367,7 @@ Only certain features set these fields: - FeatureManagedAgentLimit|
| `idp_sync_settings_role` |
| `workspace_agent` |
| `workspace_app` |
+| `task` |
## codersdk.Response
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index 8cba29f2e9..9b887b30ef 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -27,6 +27,7 @@ var AuditActionMap = map[string][]codersdk.AuditAction{
"Group": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete},
"APIKey": {codersdk.AuditActionLogin, codersdk.AuditActionLogout, codersdk.AuditActionRegister, codersdk.AuditActionCreate, codersdk.AuditActionDelete},
"License": {codersdk.AuditActionCreate, codersdk.AuditActionDelete},
+ "Task": {codersdk.AuditActionCreate, codersdk.AuditActionWrite, codersdk.AuditActionDelete},
}
type Action string
@@ -347,6 +348,18 @@ var auditableResourcesTypes = map[any]map[string]Action{
"field": ActionTrack,
"mapping": ActionTrack,
},
+ &database.TaskTable{}: {
+ "id": ActionTrack,
+ "organization_id": ActionIgnore, // Never changes.
+ "owner_id": ActionTrack,
+ "name": ActionTrack,
+ "workspace_id": ActionTrack,
+ "template_version_id": ActionTrack,
+ "template_parameters": ActionTrack,
+ "prompt": ActionTrack,
+ "created_at": ActionIgnore, // Never changes.
+ "deleted_at": ActionIgnore, // Changes, but is implicit when a delete event is fired.
+ },
}
// auditMap converts a map of struct pointers to a map of struct names as
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index c84e4ed054..71329fb318 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -3060,6 +3060,7 @@ export type ResourceType =
| "organization"
| "organization_member"
| "prebuilds_settings"
+ | "task"
| "template"
| "template_version"
| "user"
@@ -3087,6 +3088,7 @@ export const ResourceTypes: ResourceType[] = [
"organization",
"organization_member",
"prebuilds_settings",
+ "task",
"template",
"template_version",
"user",