*.audit.gwdk files declare security policy and runtime audit expectations.
They are discovered with normal .gwdk inputs, lowered into IR, and consumed by
gowdk audit; they do not generate pages, routes, or browser assets.
package security
policy admin extends "baseline.frontend" {
match "frontend"
require header "Content-Security-Policy"
deny raw_html
}
policy admin_routes {
match "/admin/**"
require guard "role:admin"
}
test headers {
expect header "Content-Security-Policy" "default-src 'self'"
}
test admin_denied {
expect GET "/admin" as "anonymous" status 403
}
Policies
Use policy <name> {} for a named policy. A policy can extend one or more
other policies:
policy browser_hardening extends "baseline.frontend" {
match "frontend"
require header "X-Frame-Options"
}
Selectors are string literals:
- Route globs:
"/admin/**","/settings/*", or"/". - Endpoint selectors:
"act:*","api:*","fragment:*","command:*", and"query:*". - Frontend selector:
"frontend".
match "<selector>" and apply to "<selector>" are equivalent.
Rules
Supported rule forms:
require csrf
require guard "role:admin"
require header "Content-Security-Policy"
require max_body "256kb"
require no_secrets_in_bundle
deny public
deny raw_html
allow raw_html "home:body"
Add as <diagnostic-code> to override the finding code for a rule:
require guard "permission:patients.read" as "audit_required_guard_missing"
Raw HTML allowlist values match either the exact source reference reported by
gowdk audit or <ownerId>:<field>.
Tests
test {} blocks become generated Go tests. gowdk audit --emit-tests writes a
readable standalone gowdk_audit_test.go; gowdk audit --run builds a
temporary generated app and runs its generated gowdkapp/gowdk_audit_test.go
with go test ./gowdkapp.
Supported expectations:
expect GET "/dashboard" status 403
expect GET "/dashboard" as "role:admin" status 200
expect header "X-Frame-Options" "DENY"
Status expectations drive the handler through runtime/testkit. Header
expectations check the runtime health endpoint so header policy can be verified
without depending on a specific page route.
Actor expectations (as "role:..." / as "permission:...") require the
generated-app audit test that gowdk build --app emits or gowdk audit --run
runs, because only that test exercises the real guard pipeline. The standalone
file from gowdk audit --emit-tests models static serving, default-deny, and
headers but installs no auth provider, so it rejects actor expectations rather
than pass or fail them for the wrong reason.
For gowdk audit --run, native RBAC actor expectations use a test-only provider
inside the temporary generated app. Production generated apps use auth.Addon
defaults when configured, or the app-owned GOWDKAuthProvider /
GOWDKGuardRegistry hooks documented for guarded routes.
Built-In Baseline
gowdk audit always composes declared policies with the built-in baseline.
Built-in policy names include:
"baseline.actions""baseline.fragments""baseline.api""baseline.contract_commands""baseline.contract_queries""baseline.frontend"
A declared policy with the same name intentionally replaces that built-in slice. Otherwise declared policies are appended and can extend the built-ins.