Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.*
80 KiB
Audit Logs
Audit Logs allows Auditors to monitor user operations in their deployment.
Note
Audit logs require a Premium license. For more details, contact your account team.
Tracked Events
We track the following resources:
| Resource | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AIGatewayKey create, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AIProvider create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AIProviderKey create, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AISeatState create |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| APIKey login, logout, register, create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AuditOAuthConvertState |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Group create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AuditableGroupAIBudget write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AuditableOrganizationMember |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AuditableUserAIBudgetOverride write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Chat create, write |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CustomRole |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GitSSHKey create |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GroupSyncSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HealthSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| License create, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NotificationTemplate |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NotificationsSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OAuth2ProviderApp |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OAuth2ProviderAppSecret |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Organization |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OrganizationSyncSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PrebuildsSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RoleSyncSettings |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TaskTable |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Template write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TemplateVersion create, write |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| User create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UserSecret create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UserSkill create, write, delete |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WorkspaceBuild start, stop |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WorkspaceProxy |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WorkspaceTable |
|
How to Filter Audit Logs
You can filter audit logs by the following parameters:
resource_type- The type of the resource, such as a workspace, template, or user. For more resource types, refer to the CoderSDK package documentation.resource_id- The ID of the resource.resource_target- The name of the resource. Can be used instead ofresource_id.action- The action applied to a resource, such ascreateordelete. For more actions, refer to the CoderSDK package documentation.username- The username of the user who triggered the action. You can also usemeas a convenient alias for the logged-in user.email- The email of the user who triggered the action.date_from- The inclusive start date with formatYYYY-MM-DD.date_to- The inclusive end date with formatYYYY-MM-DD.build_reason- The reason for the workspace build, ifresource_typeisworkspace_build. Refer to the CoderSDK package documentation for a list of valid build reasons.
Capturing/Exporting Audit Logs
In addition to the Coder dashboard, there are multiple ways to consume or query audit trails.
REST API
You can retrieve audit logs via the Coder API.
Visit the
get-audit-logs endpoint documentation
for details.
Service Logs
Audit trails are also dispatched as service logs and can be captured and categorized using any log management tool such as Splunk.
Example of a JSON formatted audit log entry:
{
"ts": "2023-06-13T03:45:37.294730279Z",
"level": "INFO",
"msg": "audit_log",
"caller": "/home/coder/coder/enterprise/audit/backends/slog.go:38",
"func": "github.com/coder/coder/v2/enterprise/audit/backends.(*SlogExporter).ExportStruct",
"logger_names": ["coderd"],
"fields": {
"ID": "033a9ffa-b54d-4c10-8ec3-2aaf9e6d741a",
"Time": "2023-06-13T03:45:37.288506Z",
"UserID": "6c405053-27e3-484a-9ad7-bcb64e7bfde6",
"OrganizationID": "00000000-0000-0000-0000-000000000000",
"Ip": null,
"UserAgent": null,
"ResourceType": "workspace_build",
"ResourceID": "ca5647e0-ef50-4202-a246-717e04447380",
"ResourceTarget": "",
"Action": "start",
"Diff": {},
"StatusCode": 200,
"AdditionalFields": {
"workspace_name": "linux-container",
"build_number": "9",
"build_reason": "initiator",
"workspace_owner": ""
},
"RequestID": "bb791ac3-f6ee-4da8-8ec2-f54e87013e93",
"ResourceIcon": ""
}
}
Example of a human readable audit log entry:
2023-06-13 03:43:29.233 [info] coderd: audit_log ID=95f7c392-da3e-480c-a579-8909f145fbe2 Time="2023-06-13T03:43:29.230422Z" UserID=6c405053-27e3-484a-9ad7-bcb64e7bfde6 OrganizationID=00000000-0000-0000-0000-000000000000 Ip=<nil> UserAgent=<nil> ResourceType=workspace_build ResourceID=988ae133-5b73-41e3-a55e-e1e9d3ef0b66 ResourceTarget="" Action=start Diff="{}" StatusCode=200 AdditionalFields="{\"workspace_name\":\"linux-container\",\"build_number\":\"7\",\"build_reason\":\"initiator\",\"workspace_owner\":\"\"}" RequestID=9682b1b5-7b9f-4bf2-9a39-9463f8e41cd6 ResourceIcon=""
Purging Old Audit Logs
Warning
Audit Logs provide critical security and compliance information. Purging Audit Logs may impact your organization's ability to investigate security incidents or meet compliance requirements. Consult your security and compliance teams before purging any audit data.
Data Retention
Coder supports configurable retention policies that automatically purge old
Audit Logs. To enable automated purging, configure the
--audit-logs-retention flag or CODER_AUDIT_LOGS_RETENTION environment
variable. For comprehensive configuration options, see
Data Retention.
Manual Purging
Alternatively, you can purge Audit Logs manually by running SQL queries directly against the database.
Audit Logs can account for a large amount of disk usage. Use the following
query to determine the amount of disk space used by the audit_logs table.
SELECT
relname AS table_name,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
pg_size_pretty(pg_relation_size(relid)) AS table_size,
pg_size_pretty(pg_indexes_size(relid)) AS indexes_size,
(SELECT COUNT(*) FROM audit_logs) AS total_records
FROM pg_catalog.pg_statio_user_tables
WHERE relname = 'audit_logs'
ORDER BY pg_total_relation_size(relid) DESC;
Should you wish to purge these records, it is safe to do so. This can only be done by running SQL queries
directly against the audit_logs table in the database. We advise users to only purge old records (>1yr)
and in accordance with your compliance requirements.
Maintenance Procedures for the Audit Logs Table
Note
VACUUM FULLacquires an exclusive lock on the table, blocking all reads and writes. For more information, see the PostgreSQL VACUUM documentation.
You may choose to run a VACUUM or VACUUM FULL operation on the audit logs table to reclaim disk space. If you choose to run the FULL operation, consider the following when doing so:
-
Run during a planned maintenance window to ensure ample time for the operation to complete and minimize impact to users
-
Stop all running instances of
coderdto prevent connection errors while the table is locked. The actual steps for this will depend on your particular deployment setup. For example, if yourcoderddeployment is running on Kubernetes:kubectl scale deployment coder --replicas=0 -n coder -
Terminate lingering connections before running the
VACUUMoperation to ensure it starts immediatelySELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'coder' AND pid <> pg_backend_pid(); -
Only
coderdneeds to scale down - external provisioner daemons, workspace proxies, and workspace agents don't connect to the database directly.
After the vacuum completes, scale coderd back up:
kubectl scale deployment coder --replicas= -n coder
Backup/Archive
Consider exporting or archiving these records before deletion:
-- Export to CSV
COPY (SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year')
TO '/path/to/audit_logs_archive.csv' DELIMITER ',' CSV HEADER;
-- Copy to archive table
CREATE TABLE audit_logs_archive AS
SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year';
Permanent Deletion
Note
For large
audit_logstables, consider running theDELETEoperation during maintenance windows as it may impact database performance. You can also batch the deletions to reduce lock time.
DELETE FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year';
-- Consider running `VACUUM VERBOSE audit_logs` afterwards for large datasets to reclaim disk space.
How to Enable Audit Logs
This feature is only available with a Premium license, and is automatically enabled.