feat: add boundary_log rbac resource (#24810)

RFC: [Bridge ↔ Boundaries Correlation
RFC](https://www.notion.so/coderhq/Gateway-and-Firewall-Correlation-RFC-31ad579be592803aa8b3d48348ccdde9)

Register a dedicated `boundary_log` RBAC resource type with `create`,
`read`, and `delete` actions, replacing the placeholder
`rbac.ResourceAuditLog` and `rbac.ResourceSystem` references previously
used in the dbauthz layer.

Create is granted at user-level so workspace agents can only write logs
owned by their workspace owner, preventing cross-workspace log
fabrication. Delete is restricted to `DBPurge` only; no human role
(including owner) can delete boundary logs.

| Subject | Create (own) | Create (other) | Read (all) | Delete |
|---|---|---|---|---|
| Workspace agent | yes | no | no | no |
| Owner (site admin) | yes (via member) | no | yes | no |
| Auditor | no | no | yes | no |
| DBPurge | no | no | no | yes |

### Changes

- **RBAC policy & resource definition**: add `boundary_log` to
`policy.go` and generate `ResourceBoundaryLog` object, scope constants,
and codersdk/TypeScript types.
- **dbauthz authorization**: replace all
`ResourceAuditLog`/`ResourceSystem` placeholders with
`ResourceBoundaryLog`. `InsertBoundaryLog` and `InsertBoundarySession`
derive the workspace owner from the agent and authorize with
`.WithOwner()` for user-scoped create.
- **Role assignments:**
- **Owner (site):** read only. Excluded from `allPermsExcept` wildcard;
create is inherited from member at user-level.
- **Member (user-level):** create. User-scoped so agents can only write
logs they own.
  - **Auditor (site):** read.
- `boundary_log` is excluded from org-admin, org-member, and
org-service-account `allPermsExcept` calls for consistency with
`ResourceBoundaryUsage`.
- **System subjects:**
- **DB Purge** (`SubjectTypeDBPurge`): delete. The only subject that can
remove boundary logs.
- **Workspace agent scope**: `ResourceBoundaryLog` with wildcard ID in
the agent scope allow-list (necessary for creation since no pre-existing
ID exists). User-level role scoping prevents deployment-wide access.
- **DB migration** (`000510_boundary_log_scopes`): add `boundary_log:*`,
`boundary_log:create`, `boundary_log:delete`, `boundary_log:read` enum
values to `api_key_scope`.
- **Test coverage**: `BoundaryLogCreate` (user-scoped, only matching
owner succeeds), `BoundaryLogDelete` (all human roles denied),
`BoundaryLogRead` (owner + auditor). dbauthz mock tests set up workspace
agent lookups for owner derivation.
- **Generated docs**: update OpenAPI specs, API reference docs, and
frontend type definitions.

---------

Co-authored-by: Muhammad Danish <mdanishkhdev@gmail.com>
Co-authored-by: Coder Agents <coder-agents-review[bot]@users.noreply.github.com>
This commit is contained in:
Sas Swart
2026-05-29 12:50:39 +02:00
committed by GitHub
co-authored by Muhammad Danish Coder Agents
parent 88060b846e
commit a586b7e5e0
32 changed files with 627 additions and 154 deletions
+15 -1
View File
@@ -320,6 +320,10 @@ const (
ApiKeyScopeUserSkillUpdate APIKeyScope = "user_skill:update"
ApiKeyScopeUserSkillDelete APIKeyScope = "user_skill:delete"
ApiKeyScopeUserSkill APIKeyScope = "user_skill:*"
ApiKeyScopeBoundaryLog APIKeyScope = "boundary_log:*"
ApiKeyScopeBoundaryLogCreate APIKeyScope = "boundary_log:create"
ApiKeyScopeBoundaryLogDelete APIKeyScope = "boundary_log:delete"
ApiKeyScopeBoundaryLogRead APIKeyScope = "boundary_log:read"
)
func (e *APIKeyScope) Scan(src interface{}) error {
@@ -580,7 +584,11 @@ func (e APIKeyScope) Valid() bool {
ApiKeyScopeUserSkillRead,
ApiKeyScopeUserSkillUpdate,
ApiKeyScopeUserSkillDelete,
ApiKeyScopeUserSkill:
ApiKeyScopeUserSkill,
ApiKeyScopeBoundaryLog,
ApiKeyScopeBoundaryLogCreate,
ApiKeyScopeBoundaryLogDelete,
ApiKeyScopeBoundaryLogRead:
return true
}
return false
@@ -810,6 +818,10 @@ func AllAPIKeyScopeValues() []APIKeyScope {
ApiKeyScopeUserSkillUpdate,
ApiKeyScopeUserSkillDelete,
ApiKeyScopeUserSkill,
ApiKeyScopeBoundaryLog,
ApiKeyScopeBoundaryLogCreate,
ApiKeyScopeBoundaryLogDelete,
ApiKeyScopeBoundaryLogRead,
}
}
@@ -4543,6 +4555,8 @@ type BoundarySession struct {
StartedAt time.Time `db:"started_at" json:"started_at"`
// Time when the session was last updated.
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
// The ID of the user who owns the workspace. NULL if the user has been deleted.
OwnerID uuid.NullUUID `db:"owner_id" json:"owner_id"`
}
// Per-replica boundary usage statistics for telemetry aggregation.